-Added support for reading single line comments

This commit is contained in:
James Newton-King
2014-01-19 12:50:56 +13:00
parent 547c3baf9e
commit c4da9cfb17
5 changed files with 254 additions and 12 deletions
@@ -2522,6 +2522,170 @@ bye", reader.Value);
Assert.AreEqual(JsonToken.EndConstructor, reader.TokenType);
}
[Test]
public void SingleLineComments()
{
string json = @"//comment*//*hi*/
{//comment
Name://comment
true//comment after true" + StringUtils.CarriageReturn + @"
,//comment after comma" + StringUtils.CarriageReturnLineFeed + @"
""ExpiryDate""://comment" + StringUtils.LineFeed + @"
new
" + StringUtils.LineFeed +
@"Date
(//comment
null//comment
),
""Price"": 3.99,
""Sizes"": //comment
[//comment
""Small""//comment
]//comment
}//comment
//comment 1 ";
JsonTextReader reader = new JsonTextReader(new StreamReader(new SlowStream(json, new UTF8Encoding(false), 1)));
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.Comment, reader.TokenType);
Assert.AreEqual("comment*//*hi*/", reader.Value);
Assert.AreEqual(2, reader.LineNumber);
Assert.IsTrue(reader.Read());
Assert.AreEqual(2, reader.LineNumber);
Assert.AreEqual(JsonToken.StartObject, reader.TokenType);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.Comment, reader.TokenType);
Assert.AreEqual(3, reader.LineNumber);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.PropertyName, reader.TokenType);
Assert.AreEqual("Name", reader.Value);
Assert.AreEqual(3, reader.LineNumber);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.Comment, reader.TokenType);
Assert.AreEqual(4, reader.LineNumber);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.Boolean, reader.TokenType);
Assert.AreEqual(true, reader.Value);
Assert.AreEqual(4, reader.LineNumber);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.Comment, reader.TokenType);
Assert.AreEqual("comment after true", reader.Value);
Assert.AreEqual(5, reader.LineNumber);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.Comment, reader.TokenType);
Assert.AreEqual("comment after comma", reader.Value);
Assert.AreEqual(7, reader.LineNumber);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.PropertyName, reader.TokenType);
Assert.AreEqual("ExpiryDate", reader.Value);
Assert.AreEqual(8, reader.LineNumber);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.Comment, reader.TokenType);
Assert.AreEqual(9, reader.LineNumber);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.StartConstructor, reader.TokenType);
Assert.AreEqual(13, reader.LineNumber);
Assert.AreEqual("Date", reader.Value);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.Comment, reader.TokenType);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.Null, reader.TokenType);
Assert.AreEqual(14, reader.LineNumber);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.Comment, reader.TokenType);
Assert.AreEqual(15, reader.LineNumber);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.EndConstructor, reader.TokenType);
Assert.AreEqual(15, reader.LineNumber);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.PropertyName, reader.TokenType);
Assert.AreEqual("Price", reader.Value);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.Float, reader.TokenType);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.PropertyName, reader.TokenType);
Assert.AreEqual("Sizes", reader.Value);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.Comment, reader.TokenType);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.StartArray, reader.TokenType);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.Comment, reader.TokenType);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.String, reader.TokenType);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.Comment, reader.TokenType);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.EndArray, reader.TokenType);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.Comment, reader.TokenType);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.EndObject, reader.TokenType);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.Comment, reader.TokenType);
Assert.AreEqual("comment ", reader.Value);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.Comment, reader.TokenType);
Assert.AreEqual("comment 1 ", reader.Value);
Assert.IsFalse(reader.Read());
}
[Test]
public void JustSinglelineComment()
{
string json = @"//comment";
JsonTextReader reader = new JsonTextReader(new StreamReader(new SlowStream(json, new UTF8Encoding(false), 1)));
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.Comment, reader.TokenType);
Assert.AreEqual("comment", reader.Value);
Assert.IsFalse(reader.Read());
}
[Test]
public void ErrorReadingComment()
{
string json = @"/";
JsonTextReader reader = new JsonTextReader(new StreamReader(new SlowStream(json, new UTF8Encoding(false), 1)));
ExceptionAssert.Throws<JsonReaderException>(
"Unexpected end while parsing comment. Path '', line 1, position 1.",
() => { reader.Read(); });
}
[Test]
public void ParseOctalNumber()
{
@@ -1383,6 +1383,54 @@ _____'propertyName': NaN
}", stringWriter.ToString());
}
}
[Test]
public void WriteComments()
{
string json = @"//comment*//*hi*/
{//comment
Name://comment
true//comment after true" + StringUtils.CarriageReturn + @"
,//comment after comma" + StringUtils.CarriageReturnLineFeed + @"
""ExpiryDate""://comment" + StringUtils.LineFeed + @"
new
" + StringUtils.LineFeed +
@"Constructor
(//comment
null//comment
),
""Price"": 3.99,
""Sizes"": //comment
[//comment
""Small""//comment
]//comment
}//comment
//comment 1 ";
JsonTextReader r = new JsonTextReader(new StringReader(json));
StringWriter sw = new StringWriter();
JsonTextWriter w = new JsonTextWriter(sw);
w.Formatting = Formatting.Indented;
w.WriteToken(r, true);
Assert.AreEqual(@"/*comment*//*hi*/*/{/*comment*/
""Name"": /*comment*/ true/*comment after true*//*comment after comma*/,
""ExpiryDate"": /*comment*/ new Constructor(
/*comment*/,
null
/*comment*/
),
""Price"": 3.99,
""Sizes"": /*comment*/ [
/*comment*/
""Small""
/*comment*/
]/*comment*/
}/*comment *//*comment 1 */", sw.ToString());
}
}
public class CustomJsonTextWriter : JsonTextWriter
@@ -75,4 +75,4 @@ using System.Security;
// by using the '*' as shown below:
[assembly: AssemblyVersion("4.5.0.0")]
[assembly: AssemblyFileVersion("6.0.1.16909")]
[assembly: AssemblyFileVersion("6.0.1.16919")]
+40 -10
View File
@@ -1310,10 +1310,19 @@ namespace Newtonsoft.Json
// should have already parsed / character before reaching this method
_charPos++;
if (!EnsureChars(1, false) || _chars[_charPos] != '*')
throw JsonReaderException.Create(this, "Error parsing comment. Expected: *, got {0}.".FormatWith(CultureInfo.InvariantCulture, _chars[_charPos]));
if (!EnsureChars(1, false))
throw JsonReaderException.Create(this, "Unexpected end while parsing comment.");
bool singlelineComment;
if (_chars[_charPos] == '*')
singlelineComment = false;
else if (_chars[_charPos] == '/')
singlelineComment = true;
else
_charPos++;
throw JsonReaderException.Create(this, "Error parsing comment. Expected: *, got {0}.".FormatWith(CultureInfo.InvariantCulture, _chars[_charPos]));
_charPos++;
int initialPosition = _charPos;
@@ -1327,7 +1336,13 @@ namespace Newtonsoft.Json
if (_charsUsed == _charPos)
{
if (ReadData(true) == 0)
throw JsonReaderException.Create(this, "Unexpected end while parsing comment.");
{
if (!singlelineComment)
throw JsonReaderException.Create(this, "Unexpected end while parsing comment.");
_stringReference = new StringReference(_chars, initialPosition, _charPos - initialPosition);
commentFinished = true;
}
}
else
{
@@ -1337,21 +1352,34 @@ namespace Newtonsoft.Json
case '*':
_charPos++;
if (EnsureChars(0, true))
if (!singlelineComment)
{
if (_chars[_charPos] == '/')
if (EnsureChars(0, true))
{
_stringReference = new StringReference(_chars, initialPosition, _charPos - initialPosition - 1);
if (_chars[_charPos] == '/')
{
_stringReference = new StringReference(_chars, initialPosition, _charPos - initialPosition - 1);
_charPos++;
commentFinished = true;
_charPos++;
commentFinished = true;
}
}
}
break;
case StringUtils.CarriageReturn:
if (singlelineComment)
{
_stringReference = new StringReference(_chars, initialPosition, _charPos - initialPosition);
commentFinished = true;
}
ProcessCarriageReturn(true);
break;
case StringUtils.LineFeed:
if (singlelineComment)
{
_stringReference = new StringReference(_chars, initialPosition, _charPos - initialPosition);
commentFinished = true;
}
ProcessLineFeed();
break;
default:
@@ -1410,7 +1438,9 @@ namespace Newtonsoft.Json
if (!EnsureChars(1, false))
return false;
return (_chars[_charPos + 1] == '*');
var nextChart = _chars[_charPos + 1];
return (nextChart == '*' || nextChart == '/');
case ')':
if (CurrentState == State.Constructor || CurrentState == State.ConstructorStart)
return true;
@@ -91,5 +91,5 @@ using System.Security;
// by using the '*' as shown below:
[assembly: AssemblyVersion("4.5.0.0")]
[assembly: AssemblyFileVersion("6.0.1.16909")]
[assembly: AssemblyFileVersion("6.0.1.16919")]
[assembly: CLSCompliant(true)]