-Added IJsonLineInfo. Implemented by JsonTextReader, JsonTokenReader, JsonValidatingReader, JToken

-Added line details to JsonTextReader exception messages and JsonValidatingReader errors
-Change JsonSchemaGenerator to disable additional properties on sealed classes
-Fixed JsonSchemaGenerator to not output enum values and options for flag enums
This commit is contained in:
JamesNK
2009-01-04 05:26:26 +00:00
parent 0319263756
commit 399033059b
26 changed files with 520 additions and 193 deletions
+1 -1
View File
@@ -241,7 +241,7 @@ now brown cow?", '"', true);
}
[Test]
[ExpectedException(typeof(JsonReaderException), ExpectedMessage = "After parsing a value an unexpected character was encoutered: t")]
[ExpectedException(typeof(JsonReaderException), ExpectedMessage = "After parsing a value an unexpected character was encoutered: t. Line 1, position 20.")]
public void TestInvalidStrings()
{
string orig = @"this is a string ""that has quotes"" ";
@@ -29,6 +29,7 @@ using System.Text;
using NUnit.Framework;
using Newtonsoft.Json;
using System.IO;
using System.Xml;
namespace Newtonsoft.Json.Tests
{
@@ -80,43 +81,63 @@ namespace Newtonsoft.Json.Tests
StringReader sr = new StringReader(input);
using (JsonReader jsonReader = new JsonTextReader(sr))
using (JsonTextReader jsonReader = new JsonTextReader(sr))
{
Assert.AreEqual(jsonReader.TokenType, JsonToken.None);
Assert.AreEqual(0, jsonReader.LineNumber);
Assert.AreEqual(0, jsonReader.LinePosition);
jsonReader.Read();
Assert.AreEqual(jsonReader.TokenType, JsonToken.StartObject);
Assert.AreEqual(1, jsonReader.LineNumber);
Assert.AreEqual(1, jsonReader.LinePosition);
jsonReader.Read();
Assert.AreEqual(jsonReader.TokenType, JsonToken.PropertyName);
Assert.AreEqual(jsonReader.Value, "CPU");
Assert.AreEqual(2, jsonReader.LineNumber);
Assert.AreEqual(6, jsonReader.LinePosition);
jsonReader.Read();
Assert.AreEqual(jsonReader.TokenType, JsonToken.String);
Assert.AreEqual(jsonReader.Value, "Intel");
Assert.AreEqual(2, jsonReader.LineNumber);
Assert.AreEqual(14, jsonReader.LinePosition);
jsonReader.Read();
Assert.AreEqual(jsonReader.TokenType, JsonToken.PropertyName);
Assert.AreEqual(jsonReader.Value, "Drives");
Assert.AreEqual(3, jsonReader.LineNumber);
Assert.AreEqual(9, jsonReader.LinePosition);
jsonReader.Read();
Assert.AreEqual(jsonReader.TokenType, JsonToken.StartArray);
Assert.AreEqual(3, jsonReader.LineNumber);
Assert.AreEqual(11, jsonReader.LinePosition);
jsonReader.Read();
Assert.AreEqual(jsonReader.TokenType, JsonToken.String);
Assert.AreEqual(jsonReader.Value, "DVD read/writer");
Assert.AreEqual(jsonReader.QuoteChar, '\'');
Assert.AreEqual(4, jsonReader.LineNumber);
Assert.AreEqual(21, jsonReader.LinePosition);
jsonReader.Read();
Assert.AreEqual(jsonReader.TokenType, JsonToken.String);
Assert.AreEqual(jsonReader.Value, "500 gigabyte hard drive");
Assert.AreEqual(jsonReader.QuoteChar, '"');
Assert.AreEqual(5, jsonReader.LineNumber);
Assert.AreEqual(29, jsonReader.LinePosition);
jsonReader.Read();
Assert.AreEqual(jsonReader.TokenType, JsonToken.EndArray);
Assert.AreEqual(6, jsonReader.LineNumber);
Assert.AreEqual(3, jsonReader.LinePosition);
jsonReader.Read();
Assert.AreEqual(jsonReader.TokenType, JsonToken.EndObject);
Assert.AreEqual(7, jsonReader.LineNumber);
Assert.AreEqual(1, jsonReader.LinePosition);
}
}
+44 -101
View File
@@ -46,18 +46,25 @@ namespace Newtonsoft.Json.Tests
new JProperty("Test4", null)
);
using (JsonReader jsonReader = new JsonTokenReader(o))
using (JsonTokenReader jsonReader = new JsonTokenReader(o))
{
IJsonLineInfo lineInfo = jsonReader;
jsonReader.Read();
Assert.AreEqual(JsonToken.StartObject, jsonReader.TokenType);
Assert.AreEqual(false, lineInfo.HasLineInfo());
jsonReader.Read();
Assert.AreEqual(JsonToken.PropertyName, jsonReader.TokenType);
Assert.AreEqual("Test1", jsonReader.Value);
Assert.AreEqual(false, lineInfo.HasLineInfo());
jsonReader.Read();
Assert.AreEqual(JsonToken.Date, jsonReader.TokenType);
Assert.AreEqual(new DateTime(2000, 10, 15, 5, 5, 5, DateTimeKind.Utc), jsonReader.Value);
Assert.AreEqual(false, lineInfo.HasLineInfo());
Assert.AreEqual(0, lineInfo.LinePosition);
Assert.AreEqual(0, lineInfo.LineNumber);
jsonReader.Read();
Assert.AreEqual(JsonToken.PropertyName, jsonReader.TokenType);
@@ -104,7 +111,7 @@ namespace Newtonsoft.Json.Tests
}
[Test]
public void ReadingIndented()
public void ReadLineInfo()
{
string input = @"{
CPU: 'Intel',
@@ -116,140 +123,76 @@ namespace Newtonsoft.Json.Tests
StringReader sr = new StringReader(input);
using (JsonReader jsonReader = new JsonTextReader(sr))
JObject o = JObject.Parse(input);
using (JsonTokenReader jsonReader = new JsonTokenReader(o))
{
IJsonLineInfo lineInfo = jsonReader;
Assert.AreEqual(jsonReader.TokenType, JsonToken.None);
Assert.AreEqual(0, lineInfo.LineNumber);
Assert.AreEqual(0, lineInfo.LinePosition);
Assert.AreEqual(false, lineInfo.HasLineInfo());
jsonReader.Read();
Assert.AreEqual(jsonReader.TokenType, JsonToken.StartObject);
Assert.AreEqual(1, lineInfo.LineNumber);
Assert.AreEqual(1, lineInfo.LinePosition);
Assert.AreEqual(true, lineInfo.HasLineInfo());
jsonReader.Read();
Assert.AreEqual(jsonReader.TokenType, JsonToken.PropertyName);
Assert.AreEqual(jsonReader.Value, "CPU");
Assert.AreEqual(2, lineInfo.LineNumber);
Assert.AreEqual(6, lineInfo.LinePosition);
Assert.AreEqual(true, lineInfo.HasLineInfo());
jsonReader.Read();
Assert.AreEqual(jsonReader.TokenType, JsonToken.String);
Assert.AreEqual(jsonReader.Value, "Intel");
Assert.AreEqual(2, lineInfo.LineNumber);
Assert.AreEqual(14, lineInfo.LinePosition);
Assert.AreEqual(true, lineInfo.HasLineInfo());
jsonReader.Read();
Assert.AreEqual(jsonReader.TokenType, JsonToken.PropertyName);
Assert.AreEqual(jsonReader.Value, "Drives");
Assert.AreEqual(3, lineInfo.LineNumber);
Assert.AreEqual(9, lineInfo.LinePosition);
Assert.AreEqual(true, lineInfo.HasLineInfo());
jsonReader.Read();
Assert.AreEqual(jsonReader.TokenType, JsonToken.StartArray);
Assert.AreEqual(3, lineInfo.LineNumber);
Assert.AreEqual(11, lineInfo.LinePosition);
Assert.AreEqual(true, lineInfo.HasLineInfo());
jsonReader.Read();
Assert.AreEqual(jsonReader.TokenType, JsonToken.String);
Assert.AreEqual(jsonReader.Value, "DVD read/writer");
Assert.AreEqual(jsonReader.QuoteChar, '\'');
Assert.AreEqual(4, lineInfo.LineNumber);
Assert.AreEqual(21, lineInfo.LinePosition);
Assert.AreEqual(true, lineInfo.HasLineInfo());
jsonReader.Read();
Assert.AreEqual(jsonReader.TokenType, JsonToken.String);
Assert.AreEqual(jsonReader.Value, "500 gigabyte hard drive");
Assert.AreEqual(jsonReader.QuoteChar, '"');
Assert.AreEqual(5, lineInfo.LineNumber);
Assert.AreEqual(29, lineInfo.LinePosition);
Assert.AreEqual(true, lineInfo.HasLineInfo());
jsonReader.Read();
Assert.AreEqual(jsonReader.TokenType, JsonToken.EndArray);
Assert.AreEqual(0, lineInfo.LineNumber);
Assert.AreEqual(0, lineInfo.LinePosition);
Assert.AreEqual(false, lineInfo.HasLineInfo());
jsonReader.Read();
Assert.AreEqual(jsonReader.TokenType, JsonToken.EndObject);
Assert.AreEqual(0, lineInfo.LineNumber);
Assert.AreEqual(0, lineInfo.LinePosition);
Assert.AreEqual(false, lineInfo.HasLineInfo());
}
}
[Test]
public void ReadingEscapedStrings()
{
string input = "{value:'Purple\\r \\n monkey\\'s:\\tdishwasher'}";
StringReader sr = new StringReader(input);
using (JsonReader jsonReader = new JsonTextReader(sr))
{
jsonReader.Read();
Assert.AreEqual(jsonReader.TokenType, JsonToken.StartObject);
jsonReader.Read();
Assert.AreEqual(jsonReader.TokenType, JsonToken.PropertyName);
jsonReader.Read();
Assert.AreEqual(jsonReader.TokenType, JsonToken.String);
Assert.AreEqual(jsonReader.Value, "Purple\r \n monkey's:\tdishwasher");
Assert.AreEqual(jsonReader.QuoteChar, '\'');
jsonReader.Read();
Assert.AreEqual(jsonReader.TokenType, JsonToken.EndObject);
}
}
[Test]
public void ReadNewlineLastCharacter()
{
string input = @"{
CPU: 'Intel',
Drives: [
'DVD read/writer',
""500 gigabyte hard drive""
]
}" + '\n';
object o = JsonConvert.DeserializeObject(input);
}
[Test]
public void WriteReadWrite()
{
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
using (JsonWriter jsonWriter = new JsonTextWriter(sw))
{
jsonWriter.WriteStartArray();
jsonWriter.WriteValue(true);
jsonWriter.WriteStartObject();
jsonWriter.WritePropertyName("integer");
jsonWriter.WriteValue(99);
jsonWriter.WritePropertyName("string");
jsonWriter.WriteValue("how now brown cow?");
jsonWriter.WritePropertyName("array");
jsonWriter.WriteStartArray();
for (int i = 0; i < 5; i++)
{
jsonWriter.WriteValue(i);
}
jsonWriter.WriteStartObject();
jsonWriter.WritePropertyName("decimal");
jsonWriter.WriteValue(990.00990099m);
jsonWriter.WriteEndObject();
jsonWriter.WriteValue(5);
jsonWriter.WriteEndArray();
jsonWriter.WriteEndObject();
jsonWriter.WriteValue("This is a string.");
jsonWriter.WriteNull();
jsonWriter.WriteNull();
jsonWriter.WriteEndArray();
}
string json = sb.ToString();
JsonSerializer serializer = new JsonSerializer();
object jsonObject = serializer.Deserialize(new JsonTextReader(new StringReader(json)));
sb = new StringBuilder();
sw = new StringWriter(sb);
using (JsonWriter jsonWriter = new JsonTextWriter(sw))
{
serializer.Serialize(sw, jsonObject);
}
Assert.AreEqual(json, sb.ToString());
}
}
}
@@ -184,7 +184,7 @@ namespace Newtonsoft.Json.Tests
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.String, reader.TokenType);
Assert.AreEqual("String 'pie' is less than minimum length of 5.", validationEventArgs.Message);
Assert.AreEqual("String 'pie' is less than minimum length of 5. Line 1, position 5.", validationEventArgs.Message);
Assert.IsNotNull(validationEventArgs);
}
@@ -208,7 +208,7 @@ namespace Newtonsoft.Json.Tests
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.String, reader.TokenType);
Assert.AreEqual("String 'The quick brown fox jumps over the lazy dog.' exceeds maximum length of 10.", validationEventArgs.Message);
Assert.AreEqual("String 'The quick brown fox jumps over the lazy dog.' exceeds maximum length of 10. Line 1, position 46.", validationEventArgs.Message);
Assert.IsNotNull(validationEventArgs);
}
@@ -245,7 +245,7 @@ namespace Newtonsoft.Json.Tests
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.String, reader.TokenType);
Assert.AreEqual(@"Value ""THREE"" is not defined in enum.", validationEventArgs.Message);
Assert.AreEqual(@"Value ""THREE"" is not defined in enum. Line 1, position 20.", validationEventArgs.Message);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.EndArray, reader.TokenType);
@@ -271,7 +271,7 @@ namespace Newtonsoft.Json.Tests
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.String, reader.TokenType);
Assert.AreEqual("String 'The quick brown fox jumps over the lazy dog.' does not match regex pattern 'foo'.", validationEventArgs.Message);
Assert.AreEqual("String 'The quick brown fox jumps over the lazy dog.' does not match regex pattern 'foo'. Line 1, position 46.", validationEventArgs.Message);
Assert.IsNotNull(validationEventArgs);
}
@@ -294,13 +294,13 @@ namespace Newtonsoft.Json.Tests
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.Integer, reader.TokenType);
Assert.AreEqual("Integer 10 exceeds maximum value of 5.", validationEventArgs.Message);
Assert.AreEqual("Integer 10 exceeds maximum value of 5. Line 1, position 2.", validationEventArgs.Message);
Assert.IsNotNull(validationEventArgs);
}
[Test]
[ExpectedException(typeof(JsonSchemaException), ExpectedMessage = "Integer 10 exceeds maximum value of 5.")]
[ExpectedException(typeof(JsonSchemaException), ExpectedMessage = "Integer 10 exceeds maximum value of 5. Line 1, position 2.")]
public void ThrowExceptionWhenNoValidationEventHandler()
{
string schemaJson = @"{
@@ -332,7 +332,7 @@ namespace Newtonsoft.Json.Tests
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.Integer, reader.TokenType);
Assert.AreEqual("Integer 1 is less than minimum value of 5.", validationEventArgs.Message);
Assert.AreEqual("Integer 1 is less than minimum value of 5. Line 1, position 1.", validationEventArgs.Message);
Assert.IsNotNull(validationEventArgs);
}
@@ -369,7 +369,7 @@ namespace Newtonsoft.Json.Tests
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.Integer, reader.TokenType);
Assert.AreEqual(@"Value 3 is not defined in enum.", validationEventArgs.Message);
Assert.AreEqual(@"Value 3 is not defined in enum. Line 1, position 7.", validationEventArgs.Message);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.EndArray, reader.TokenType);
@@ -395,7 +395,7 @@ namespace Newtonsoft.Json.Tests
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.Float, reader.TokenType);
Assert.AreEqual("Float 10.0 exceeds maximum value of 5.", validationEventArgs.Message);
Assert.AreEqual("Float 10.0 exceeds maximum value of 5. Line 1, position 4.", validationEventArgs.Message);
Assert.IsNotNull(validationEventArgs);
}
@@ -418,7 +418,7 @@ namespace Newtonsoft.Json.Tests
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.Float, reader.TokenType);
Assert.AreEqual("Float 1.1 is less than minimum value of 5.", validationEventArgs.Message);
Assert.AreEqual("Float 1.1 is less than minimum value of 5. Line 1, position 3.", validationEventArgs.Message);
Assert.IsNotNull(validationEventArgs);
}
@@ -455,7 +455,7 @@ namespace Newtonsoft.Json.Tests
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.Float, reader.TokenType);
Assert.AreEqual(@"Value 3.0 is not defined in enum.", validationEventArgs.Message);
Assert.AreEqual(@"Value 3.0 is not defined in enum. Line 1, position 13.", validationEventArgs.Message);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.EndArray, reader.TokenType);
@@ -494,7 +494,7 @@ namespace Newtonsoft.Json.Tests
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.Float, reader.TokenType);
Assert.AreEqual(@"Float 4.001 exceeds the maximum allowed number decimal places of 2.", validationEventArgs.Message);
Assert.AreEqual(@"Float 4.001 exceeds the maximum allowed number decimal places of 2. Line 1, position 15.", validationEventArgs.Message);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.EndArray, reader.TokenType);
@@ -527,7 +527,7 @@ namespace Newtonsoft.Json.Tests
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.Null, reader.TokenType);
Assert.AreEqual(@"Value null is not defined in enum.", validationEventArgs.Message);
Assert.AreEqual(@"Value null is not defined in enum. Line 1, position 6.", validationEventArgs.Message);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.EndArray, reader.TokenType);
@@ -564,7 +564,7 @@ namespace Newtonsoft.Json.Tests
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.Boolean, reader.TokenType);
Assert.AreEqual(@"Value false is not defined in enum.", validationEventArgs.Message);
Assert.AreEqual(@"Value false is not defined in enum. Line 1, position 12.", validationEventArgs.Message);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.EndArray, reader.TokenType);
@@ -603,7 +603,7 @@ namespace Newtonsoft.Json.Tests
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.EndArray, reader.TokenType);
Assert.AreEqual("Array item count 4 exceeds maximum count of 3.", validationEventArgs.Message);
Assert.AreEqual("Array item count 4 exceeds maximum count of 3. Line 1, position 21.", validationEventArgs.Message);
Assert.IsNotNull(validationEventArgs);
}
@@ -633,7 +633,7 @@ namespace Newtonsoft.Json.Tests
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.EndArray, reader.TokenType);
Assert.AreEqual("Array item count 1 is less than minimum count of 2.", validationEventArgs.Message);
Assert.AreEqual("Array item count 1 is less than minimum count of 2. Line 1, position 6.", validationEventArgs.Message);
Assert.IsNotNull(validationEventArgs);
}
@@ -658,7 +658,7 @@ namespace Newtonsoft.Json.Tests
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.StartArray, reader.TokenType);
Assert.AreEqual(@"Invalid type. Expected String but got Array.", validationEventArgs.Message);
Assert.AreEqual(@"Invalid type. Expected String but got Array. Line 1, position 1.", validationEventArgs.Message);
Assert.IsNotNull(validationEventArgs);
}
@@ -691,7 +691,7 @@ namespace Newtonsoft.Json.Tests
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.Float, reader.TokenType);
Assert.AreEqual(@"Type Float is disallowed.", validationEventArgs.Message);
Assert.AreEqual(@"Type Float is disallowed. Line 1, position 11.", validationEventArgs.Message);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.EndArray, reader.TokenType);
@@ -735,7 +735,7 @@ namespace Newtonsoft.Json.Tests
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.EndObject, reader.TokenType);
Assert.AreEqual("Non-optional properties are missing from object: hobbies, age", validationEventArgs.Message);
Assert.AreEqual("Non-optional properties are missing from object: hobbies, age. Line 1, position 16.", validationEventArgs.Message);
Assert.IsNotNull(validationEventArgs);
}
@@ -820,7 +820,7 @@ namespace Newtonsoft.Json.Tests
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.Null, reader.TokenType);
Assert.AreEqual(null, reader.Value);
Assert.AreEqual("Property 'additionalProperty1' has not been defined and schema does not allow additional properties.", validationEventArgs.Message);
Assert.AreEqual("Property 'additionalProperty1' has not been defined and the schema does not allow additional properties. Line 1, position 38.", validationEventArgs.Message);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.PropertyName, reader.TokenType);
@@ -829,7 +829,7 @@ namespace Newtonsoft.Json.Tests
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.Null, reader.TokenType);
Assert.AreEqual(null, reader.Value);
Assert.AreEqual("Property 'additionalProperty2' has not been defined and schema does not allow additional properties.", validationEventArgs.Message);
Assert.AreEqual("Property 'additionalProperty2' has not been defined and the schema does not allow additional properties. Line 1, position 65.", validationEventArgs.Message);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.EndObject, reader.TokenType);
@@ -861,7 +861,7 @@ namespace Newtonsoft.Json.Tests
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.String, reader.TokenType);
Assert.AreEqual(1, errors.Count);
Assert.AreEqual("String 'The quick brown fox jumps over the lazy dog.' exceeds maximum length of 9.", errors[0]);
Assert.AreEqual("String 'The quick brown fox jumps over the lazy dog.' exceeds maximum length of 9. Line 1, position 46.", errors[0]);
Assert.IsNotNull(validationEventArgs);
}
@@ -933,7 +933,7 @@ namespace Newtonsoft.Json.Tests
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.PropertyName, reader.TokenType);
Assert.AreEqual("additional", reader.Value.ToString());
Assert.AreEqual("Property 'additional' has not been defined and schema does not allow additional properties.", validationEventArgs.Message);
Assert.AreEqual("Property 'additional' has not been defined and the schema does not allow additional properties. Line 1, position 62.", validationEventArgs.Message);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.String, reader.TokenType);
@@ -942,7 +942,7 @@ namespace Newtonsoft.Json.Tests
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.PropertyName, reader.TokenType);
Assert.AreEqual("additional2", reader.Value.ToString());
Assert.AreEqual("Property 'additional2' has not been defined and schema does not allow additional properties.", validationEventArgs.Message);
Assert.AreEqual("Property 'additional2' has not been defined and the schema does not allow additional properties. Line 1, position 84.", validationEventArgs.Message);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.String, reader.TokenType);
@@ -972,7 +972,7 @@ namespace Newtonsoft.Json.Tests
Assert.AreEqual(JsonToken.EndObject, reader.TokenType);
Assert.AreEqual(1, errors.Count);
Assert.AreEqual("Non-optional properties are missing from object: secondproperty, firstproperty", errors[0]);
Assert.AreEqual("Non-optional properties are missing from object: secondproperty, firstproperty. Line 1, position 2.", errors[0]);
}
[Test]
@@ -997,15 +997,15 @@ namespace Newtonsoft.Json.Tests
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.Integer, reader.TokenType);
Assert.AreEqual("Invalid type. Expected String but got Integer.", validationEventArgs.Message);
Assert.AreEqual("Invalid type. Expected String but got Integer. Line 1, position 3.", validationEventArgs.Message);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.String, reader.TokenType);
Assert.AreEqual("Invalid type. Expected Integer but got String.", validationEventArgs.Message);
Assert.AreEqual("Invalid type. Expected Integer but got String. Line 1, position 7.", validationEventArgs.Message);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.Null, reader.TokenType);
Assert.AreEqual("Index 3 has not been defined and schema does not allow additional items.", validationEventArgs.Message);
Assert.AreEqual("Index 3 has not been defined and the schema does not allow additional items. Line 1, position 14.", validationEventArgs.Message);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.EndArray, reader.TokenType);
@@ -1103,7 +1103,7 @@ namespace Newtonsoft.Json.Tests
Assert.AreEqual(JsonToken.String, reader.TokenType);
Assert.AreEqual("secasecasecasecaseca", reader.Value.ToString());
Assert.AreEqual(1, errors.Count);
Assert.AreEqual("String 'secasecasecasecaseca' exceeds maximum length of 10.", errors[0]);
Assert.AreEqual("String 'secasecasecasecaseca' exceeds maximum length of 10. Line 3, position 41.", errors[0]);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.PropertyName, reader.TokenType);
@@ -1123,9 +1123,9 @@ namespace Newtonsoft.Json.Tests
Assert.AreEqual(JsonToken.String, reader.TokenType);
Assert.AreEqual("aaa", reader.Value.ToString());
Assert.AreEqual(4, errors.Count);
Assert.AreEqual("String 'aaa' is less than minimum length of 7.", errors[1]);
Assert.AreEqual("String 'aaa' does not match regex pattern 'hi'.", errors[2]);
Assert.AreEqual("String 'aaa' does not match regex pattern 'hi2u'.", errors[3]);
Assert.AreEqual("String 'aaa' is less than minimum length of 7. Line 5, position 39.", errors[1]);
Assert.AreEqual("String 'aaa' does not match regex pattern 'hi'. Line 5, position 39.", errors[2]);
Assert.AreEqual("String 'aaa' does not match regex pattern 'hi2u'. Line 5, position 39.", errors[3]);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.PropertyName, reader.TokenType);
@@ -1136,7 +1136,7 @@ namespace Newtonsoft.Json.Tests
Assert.AreEqual(JsonToken.String, reader.TokenType);
Assert.AreEqual("three", reader.Value.ToString());
Assert.AreEqual(5, errors.Count);
Assert.AreEqual("String 'three' is less than minimum length of 6.", errors[4]);
Assert.AreEqual("String 'three' is less than minimum length of 6. Line 6, position 24.", errors[4]);
Assert.IsTrue(reader.Read());
Assert.AreEqual(JsonToken.EndObject, reader.TokenType);
@@ -67,6 +67,7 @@
<Reference Include="System.ServiceModel.Web">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Web" />
<Reference Include="System.Web.Extensions">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
@@ -80,5 +80,31 @@ namespace Newtonsoft.Json.Tests.Schema
JToken stringToken = JToken.FromObject("pie lol");
stringToken.Validate(schema);
}
[Test]
public void ValidateFailureWithOutLineInfoBecauseOfEndToken()
{
JsonSchema schema = JsonSchema.Parse("{'properties':{'lol':{}}}");
JObject o = JObject.Parse("{}");
List<string> errors = new List<string>();
o.Validate(schema, (sender, args) => errors.Add(args.Message));
Assert.AreEqual("Non-optional properties are missing from object: lol.", errors[0]);
Assert.AreEqual(1, errors.Count);
}
[Test]
public void ValidateFailureWithLineInfo()
{
JsonSchema schema = JsonSchema.Parse("{'properties':{'lol':{'type':'string'}}}");
JObject o = JObject.Parse("{'lol':1}");
List<string> errors = new List<string>();
o.Validate(schema, (sender, args) => errors.Add(args.Message));
Assert.AreEqual("Invalid type. Expected String but got Integer. Line 1, position 9.", errors[0]);
Assert.AreEqual(1, errors.Count);
}
}
}
@@ -24,11 +24,18 @@
#endregion
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
using Newtonsoft.Json.Tests.TestObjects;
using Newtonsoft.Json.Utilities;
using NUnit.Framework;
using Newtonsoft.Json.Schema;
using System.IO;
using System.Linq;
using Newtonsoft.Json.Linq;
namespace Newtonsoft.Json.Tests.Schema
{
@@ -65,6 +72,7 @@ namespace Newtonsoft.Json.Tests.Schema
Assert.AreEqual(@"{
""description"": ""DefaultValueAttributeTestClass description!"",
""type"": ""object"",
""additionalProperties"": false,
""properties"": {
""TestField1"": {
""type"": ""integer"",
@@ -261,5 +269,113 @@ namespace Newtonsoft.Json.Tests.Schema
Assert.AreEqual(JsonSchemaType.Object, schema.Properties["Child"].Type);
Assert.AreEqual(schema, schema.Properties["Child"]);
}
[Test]
public void GenerateSchemaForType()
{
JsonSchemaGenerator generator = new JsonSchemaGenerator();
generator.UndefinedSchemaIdHandling = UndefinedSchemaIdHandling.UseTypeName;
JsonSchema schema = generator.Generate(typeof(Type));
Assert.AreEqual(JsonSchemaType.String, schema.Type);
}
public class CustomDirectoryInfoSerializer : JsonSerializer
{
protected override Newtonsoft.Json.Serialization.JsonMemberMappingCollection GetMemberMappings(Type objectType)
{
JsonMemberMappingCollection mappings = base.GetMemberMappings(objectType);
JsonMemberMappingCollection c = new JsonMemberMappingCollection();
CollectionUtils.AddRange(c, (IEnumerable) mappings.Where(m => m.MappingName != "Root"));
return c;
}
}
[Test]
public void GenerateSchemaForDirectoryInfo()
{
JsonSchemaGenerator generator = new JsonSchemaGenerator();
generator.UndefinedSchemaIdHandling = UndefinedSchemaIdHandling.UseTypeName;
JsonSchema schema = generator.Generate(typeof(DirectoryInfo), true);
string json = schema.ToString();
Assert.AreEqual(@"{
""id"": ""System.IO.DirectoryInfo"",
""type"": [
""object"",
""null""
],
""additionalProperties"": false,
""properties"": {
""Name"": {
""type"": [
""string"",
""null""
]
},
""Parent"": {
""$ref"": ""System.IO.DirectoryInfo""
},
""Exists"": {
""type"": ""boolean""
},
""Root"": {
""$ref"": ""System.IO.DirectoryInfo""
},
""FullName"": {
""type"": [
""string"",
""null""
]
},
""Extension"": {
""type"": [
""string"",
""null""
]
},
""CreationTime"": {
""type"": ""string""
},
""CreationTimeUtc"": {
""type"": ""string""
},
""LastAccessTime"": {
""type"": ""string""
},
""LastAccessTimeUtc"": {
""type"": ""string""
},
""LastWriteTime"": {
""type"": ""string""
},
""LastWriteTimeUtc"": {
""type"": ""string""
},
""Attributes"": {
""type"": ""integer""
}
}
}", json);
DirectoryInfo temp = new DirectoryInfo(@"c:\temp");
JsonTokenWriter jsonWriter = new JsonTokenWriter();
CustomDirectoryInfoSerializer customSerializer = new CustomDirectoryInfoSerializer();
customSerializer.Converters.Add(new IsoDateTimeConverter());
customSerializer.Serialize(jsonWriter, temp);
List<string> errors = new List<string>();
jsonWriter.Token.Validate(schema, (sender, args) => errors.Add(args.Message));
Assert.AreEqual(2, errors.Count);
Assert.AreEqual("Non-optional properties are missing from object: Root.", errors[0]);
Assert.AreEqual("Non-optional properties are missing from object: Root.", errors[1]);
}
}
}
@@ -30,7 +30,7 @@ namespace Newtonsoft.Json.Tests.TestObjects
#if !PocketPC
[Description("DefaultValueAttributeTestClass description!")]
#endif
public class DefaultValueAttributeTestClass
public sealed class DefaultValueAttributeTestClass
{
[DefaultValue("TestProperty1Value")]
public string TestProperty1 { get; set; }
+15
View File
@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Newtonsoft.Json
{
public interface IJsonLineInfo
{
bool HasLineInfo();
int LineNumber { get; }
int LinePosition { get; }
}
}
@@ -34,6 +34,9 @@ namespace Newtonsoft.Json
/// </summary>
public class JsonReaderException : Exception
{
public int LineNumber { get; private set; }
public int LinePosition { get; private set; }
/// <summary>
/// Initializes a new instance of the <see cref="JsonReaderException"/> class.
/// </summary>
@@ -61,5 +64,12 @@ namespace Newtonsoft.Json
: base(message, innerException)
{
}
internal JsonReaderException(string message, Exception innerException, int lineNumber, int linePosition)
: base(message, innerException)
{
LineNumber = lineNumber;
LinePosition = linePosition;
}
}
}
+79 -32
View File
@@ -29,19 +29,21 @@ using System.Text;
using System.IO;
using System.Xml;
using System.Globalization;
using Newtonsoft.Json.Utilities;
namespace Newtonsoft.Json
{
/// <summary>
/// Represents a reader that provides fast, non-cached, forward-only access to serialized Json data.
/// </summary>
public class JsonTextReader : JsonReader
public class JsonTextReader : JsonReader, IJsonLineInfo
{
private TextReader _reader;
private readonly TextReader _reader;
private readonly StringBuffer _buffer;
private char _currentChar;
// current Token data
private StringBuffer _buffer;
private int _currentLinePosition;
private int _currentLineNumber;
private bool _currentCharCarriageReturn;
/// <summary>
/// Initializes a new instance of the <see cref="JsonReader"/> class with the specified <see cref="TextReader"/>.
@@ -54,6 +56,7 @@ namespace Newtonsoft.Json
_reader = reader;
_buffer = new StringBuffer(4096);
_currentLineNumber = 1;
}
private void ParseString(char quote)
@@ -100,7 +103,7 @@ namespace Newtonsoft.Json
}
else
{
throw new JsonReaderException("Unterminated string. Expected delimiter: " + quote);
throw CreateJsonReaderException("Unterminated string. Expected delimiter: {0}. Line {1}, position {2}.", quote, _currentLineNumber, _currentLinePosition);
}
break;
case '"':
@@ -130,7 +133,7 @@ namespace Newtonsoft.Json
}
if (!stringTerminated)
throw new JsonReaderException("Unterminated string. Expected delimiter: " + quote);
throw CreateJsonReaderException("Unterminated string. Expected delimiter: {0}. Line {1}, position {2}.", quote, _currentLineNumber, _currentLinePosition);
ClearCurrentChar();
string text = _buffer.ToString();
@@ -147,6 +150,12 @@ namespace Newtonsoft.Json
}
}
private JsonReaderException CreateJsonReaderException(string format, params object[] args)
{
string message = format.FormatWith(CultureInfo.InvariantCulture, args);
return new JsonReaderException(message, null, _currentLineNumber, _currentLinePosition);
}
/// <summary>
/// Sets the current token and value.
/// </summary>
@@ -218,20 +227,37 @@ namespace Newtonsoft.Json
SetToken(JsonToken.Date, dateTime);
}
private const int LineFeedValue = StringUtils.LineFeed;
private const int CarriageReturnValue = StringUtils.CarriageReturn;
private bool MoveNext()
{
int value = _reader.Read();
if (value != -1)
switch (value)
{
_currentChar = (char)value;
//_testBuffer.Append(_currentChar);
return true;
}
else
{
return false;
case -1:
return false;
case CarriageReturnValue:
_currentLineNumber++;
_currentLinePosition = 0;
_currentCharCarriageReturn = true;
break;
case LineFeedValue:
if (!_currentCharCarriageReturn)
_currentLineNumber++;
_currentLinePosition = 0;
_currentCharCarriageReturn = false;
break;
default:
_currentLinePosition++;
_currentCharCarriageReturn = false;
break;
}
_currentChar = (char)value;
return true;
}
private bool HasNext()
@@ -300,7 +326,7 @@ namespace Newtonsoft.Json
case State.Error:
break;
default:
throw new JsonReaderException("Unexpected state: " + CurrentState);
throw CreateJsonReaderException("Unexpected state: {0}. Line {1}, position {2}.", CurrentState, _currentLineNumber, _currentLinePosition);
}
}
}
@@ -339,7 +365,7 @@ namespace Newtonsoft.Json
}
else
{
throw new JsonReaderException("After parsing a value an unexpected character was encoutered: " + _currentChar);
throw CreateJsonReaderException("After parsing a value an unexpected character was encoutered: {0}. Line {1}, position {2}.", _currentChar, _currentLineNumber, _currentLinePosition);
}
break;
}
@@ -395,7 +421,7 @@ namespace Newtonsoft.Json
}
else
{
throw new JsonReaderException("Invalid property identifier character: " + _currentChar);
throw CreateJsonReaderException("Invalid property identifier character: {0}. Line {1}, position {2}.", _currentChar, _currentLineNumber, _currentLinePosition);
}
// finished property. move to colon
@@ -426,7 +452,7 @@ namespace Newtonsoft.Json
}
}
throw new JsonReaderException("Unclosed quoted property. Expected: " + quoteChar);
throw CreateJsonReaderException("Unclosed quoted property. Expected: {0}. Line {1}, position {2}.", quoteChar, _currentLineNumber, _currentLinePosition);
}
private bool ValidIdentifierChar(char value)
@@ -451,7 +477,7 @@ namespace Newtonsoft.Json
}
else
{
throw new JsonReaderException("Invalid JavaScript property identifier character: " + _currentChar);
throw CreateJsonReaderException("Invalid JavaScript property identifier character: {0}. Line {1}, position {2}.", _currentChar, _currentLineNumber, _currentLinePosition);
}
}
}
@@ -482,11 +508,11 @@ namespace Newtonsoft.Json
else if (next == 'e')
ParseConstructor();
else
throw new JsonReaderException("Unexpected character encountered while parsing value: " + _currentChar);
throw CreateJsonReaderException("Unexpected character encountered while parsing value: {0}. Line {1}, position {2}.", _currentChar, _currentLineNumber, _currentLinePosition);
}
else
{
throw new JsonReaderException("Unexpected end");
throw CreateJsonReaderException("Unexpected end. Line {0}, position {1}.", _currentLineNumber, _currentLinePosition);
}
return true;
case 'N':
@@ -538,7 +564,7 @@ namespace Newtonsoft.Json
}
else
{
throw new JsonReaderException("Unexpected character encountered while parsing value: " + _currentChar);
throw CreateJsonReaderException("Unexpected character encountered while parsing value: {0}. Line {1}, position {2}.", _currentChar, _currentLineNumber, _currentLinePosition);
}
break;
}
@@ -574,7 +600,7 @@ namespace Newtonsoft.Json
EatWhitespace(false);
if (_currentChar != '(')
throw new JsonReaderException("Unexpected character while parsing constructor: " + _currentChar);
throw CreateJsonReaderException("Unexpected character while parsing constructor: {0}. Line {1}, position {2}.", _currentChar, _currentLineNumber, _currentLinePosition);
string constructorName = _buffer.ToString();
_buffer.Position = 0;
@@ -655,7 +681,7 @@ namespace Newtonsoft.Json
}
else
{
throw new JsonReaderException("Error parsing comment. Expected: *");
throw CreateJsonReaderException("Error parsing comment. Expected: *. Line {0}, position {1}.", _currentLineNumber, _currentLinePosition);
}
SetToken(JsonToken.Comment, _buffer.ToString());
@@ -735,7 +761,7 @@ namespace Newtonsoft.Json
}
else
{
throw new JsonReaderException("Error parsing boolean value.");
throw CreateJsonReaderException("Error parsing boolean value. Line {0}, position {1}.", _currentLineNumber, _currentLinePosition);
}
}
@@ -747,7 +773,7 @@ namespace Newtonsoft.Json
}
else
{
throw new JsonReaderException("Error parsing null value.");
throw CreateJsonReaderException("Error parsing null value. Line {0}, position {1}.", _currentLineNumber, _currentLinePosition);
}
}
@@ -759,7 +785,7 @@ namespace Newtonsoft.Json
}
else
{
throw new JsonReaderException("Error parsing undefined value.");
throw CreateJsonReaderException("Error parsing undefined value. Line {0}, position {1}.", _currentLineNumber, _currentLinePosition);
}
}
@@ -771,7 +797,7 @@ namespace Newtonsoft.Json
}
else
{
throw new JsonReaderException("Error parsing boolean value.");
throw CreateJsonReaderException("Error parsing boolean value. Line {0}, position {1}.", _currentLineNumber, _currentLinePosition);
}
}
@@ -783,7 +809,7 @@ namespace Newtonsoft.Json
}
else
{
throw new JsonReaderException("Error parsing negative infinity value.");
throw CreateJsonReaderException("Error parsing negative infinity value. Line {0}, position {1}.", _currentLineNumber, _currentLinePosition);
}
}
@@ -795,7 +821,7 @@ namespace Newtonsoft.Json
}
else
{
throw new JsonReaderException("Error parsing positive infinity value.");
throw CreateJsonReaderException("Error parsing positive infinity value. Line {0}, position {1}.", _currentLineNumber, _currentLinePosition);
}
}
@@ -807,7 +833,7 @@ namespace Newtonsoft.Json
}
else
{
throw new JsonReaderException("Error parsing NaN value.");
throw CreateJsonReaderException("Error parsing NaN value. Line {0}, position {1}.", _currentLineNumber, _currentLinePosition);
}
}
@@ -824,5 +850,26 @@ namespace Newtonsoft.Json
if (_buffer != null)
_buffer.Clear();
}
public bool HasLineInfo()
{
return true;
}
public int LineNumber
{
get
{
if (CurrentState == State.Start)
return 0;
return _currentLineNumber;
}
}
public int LinePosition
{
get { return _currentLinePosition; }
}
}
}
+35 -5
View File
@@ -35,7 +35,7 @@ using System.Text.RegularExpressions;
namespace Newtonsoft.Json
{
public class JsonValidatingReader : JsonReader
public class JsonValidatingReader : JsonReader, IJsonLineInfo
{
private class SchemaScope
{
@@ -186,7 +186,13 @@ namespace Newtonsoft.Json
private void RaiseError(string message, JsonSchemaModel schema)
{
OnValidationEvent(new JsonSchemaException(message));
IJsonLineInfo lineInfo = this;
string exceptionMessage = (lineInfo.HasLineInfo())
? message + " Line {0}, position {1}.".FormatWith(CultureInfo.InvariantCulture, lineInfo.LineNumber, lineInfo.LinePosition)
: message;
OnValidationEvent(new JsonSchemaException(exceptionMessage, null, lineInfo.LineNumber, lineInfo.LinePosition));
}
private void OnValidationEvent(JsonSchemaException exception)
@@ -362,7 +368,7 @@ namespace Newtonsoft.Json
requiredProperties.Where(kv => !kv.Value).Select(kv => kv.Key).ToList();
if (unmatchedRequiredProperties.Count > 0)
RaiseError("Non-optional properties are missing from object: {0}".FormatWith(CultureInfo.InvariantCulture, string.Join(", ", unmatchedRequiredProperties.ToArray())), schema);
RaiseError("Non-optional properties are missing from object: {0}.".FormatWith(CultureInfo.InvariantCulture, string.Join(", ", unmatchedRequiredProperties.ToArray())), schema);
}
}
@@ -456,7 +462,7 @@ namespace Newtonsoft.Json
_currentScope.ArrayItemCount++;
if (CurrentSchema != null && CurrentSchema.Items != null && CurrentSchema.Items.Count > 1 && _currentScope.ArrayItemCount >= CurrentSchema.Items.Count)
RaiseError("Index {0} has not been defined and schema does not allow additional items.".FormatWith(CultureInfo.InvariantCulture, _currentScope.ArrayItemCount), CurrentSchema);
RaiseError("Index {0} has not been defined and the schema does not allow additional items.".FormatWith(CultureInfo.InvariantCulture, _currentScope.ArrayItemCount), CurrentSchema);
}
}
@@ -498,7 +504,7 @@ namespace Newtonsoft.Json
if (!schema.AllowAdditionalProperties && !definedProperties.Contains(propertyName))
{
RaiseError("Property '{0}' has not been defined and schema does not allow additional properties.".FormatWith(CultureInfo.InvariantCulture, propertyName), schema);
RaiseError("Property '{0}' has not been defined and the schema does not allow additional properties.".FormatWith(CultureInfo.InvariantCulture, propertyName), schema);
}
}
@@ -531,5 +537,29 @@ namespace Newtonsoft.Json
return true;
}
bool IJsonLineInfo.HasLineInfo()
{
IJsonLineInfo lineInfo = _reader as IJsonLineInfo;
return (lineInfo != null) ? lineInfo.HasLineInfo() : false;
}
int IJsonLineInfo.LineNumber
{
get
{
IJsonLineInfo lineInfo = _reader as IJsonLineInfo;
return (lineInfo != null) ? lineInfo.LineNumber : 0;
}
}
int IJsonLineInfo.LinePosition
{
get
{
IJsonLineInfo lineInfo = _reader as IJsonLineInfo;
return (lineInfo != null) ? lineInfo.LinePosition : 0;
}
}
}
}
+4 -5
View File
@@ -105,15 +105,14 @@ namespace Newtonsoft.Json.Linq
throw new Exception("Error reading JArray from JsonReader.");
}
if (reader.TokenType != JsonToken.StartArray)
throw new Exception(
"Error reading JArray from JsonReader. Current JsonReader item is not an array: {0}".FormatWith(
CultureInfo.InvariantCulture, reader.TokenType));
throw new Exception("Error reading JArray from JsonReader. Current JsonReader item is not an array: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
JArray a = new JArray();
a.SetLineInfo(reader as IJsonLineInfo);
if (!reader.Read())
throw new Exception("Error reading JArray from JsonReader.");
JArray a = new JArray();
a.ReadContentFrom(reader);
return a;
+2 -3
View File
@@ -175,11 +175,10 @@ namespace Newtonsoft.Json.Linq
}
if (reader.TokenType != JsonToken.StartConstructor)
throw new Exception(
"Error reading JConstructor from JsonReader. Current JsonReader item is not a constructor: {0}".FormatWith(
CultureInfo.InvariantCulture, reader.TokenType));
throw new Exception("Error reading JConstructor from JsonReader. Current JsonReader item is not a constructor: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
JConstructor c = new JConstructor((string)reader.Value);
c.SetLineInfo(reader as IJsonLineInfo);
if (!reader.Read())
throw new Exception("Error reading JConstructor from JsonReader.");
+17 -4
View File
@@ -365,6 +365,7 @@ namespace Newtonsoft.Json.Linq
internal void ReadContentFrom(JsonReader r)
{
ValidationUtils.ArgumentNotNull(r, "r");
IJsonLineInfo lineInfo = r as IJsonLineInfo;
JContainer parent = this;
@@ -385,6 +386,7 @@ namespace Newtonsoft.Json.Linq
break;
case JsonToken.StartArray:
JArray a = new JArray();
a.SetLineInfo(lineInfo);
parent.AddObjectSkipNotify(a);
parent = a;
break;
@@ -397,6 +399,7 @@ namespace Newtonsoft.Json.Linq
break;
case JsonToken.StartObject:
JObject o = new JObject();
o.SetLineInfo(lineInfo);
parent.AddObjectSkipNotify(o);
parent = o;
break;
@@ -408,6 +411,7 @@ namespace Newtonsoft.Json.Linq
break;
case JsonToken.StartConstructor:
JConstructor constructor = new JConstructor(r.Value.ToString());
constructor.SetLineInfo(constructor);
parent.AddObjectSkipNotify(constructor);
parent = constructor;
break;
@@ -422,19 +426,28 @@ namespace Newtonsoft.Json.Linq
case JsonToken.Float:
case JsonToken.Date:
case JsonToken.Boolean:
parent.AddObjectSkipNotify(new JValue(r.Value));
JValue v = new JValue(r.Value);
v.SetLineInfo(lineInfo);
parent.AddObjectSkipNotify(v);
break;
case JsonToken.Comment:
parent.AddObjectSkipNotify(JValue.CreateComment(r.Value.ToString()));
v = JValue.CreateComment(r.Value.ToString());
v.SetLineInfo(lineInfo);
parent.AddObjectSkipNotify(v);
break;
case JsonToken.Null:
parent.AddObjectSkipNotify(new JValue(null, JsonTokenType.Null));
v = new JValue(null, JsonTokenType.Null);
v.SetLineInfo(lineInfo);
parent.AddObjectSkipNotify(v);
break;
case JsonToken.Undefined:
parent.AddObjectSkipNotify(new JValue(null, JsonTokenType.Undefined));
v = new JValue(null, JsonTokenType.Undefined);
v.SetLineInfo(lineInfo);
parent.AddObjectSkipNotify(v);
break;
case JsonToken.PropertyName:
JProperty property = new JProperty(r.Value.ToString());
property.SetLineInfo(lineInfo);
parent.AddObjectSkipNotify(property);
parent = property;
break;
+3 -1
View File
@@ -196,10 +196,12 @@ namespace Newtonsoft.Json.Linq
"Error reading JObject from JsonReader. Current JsonReader item is not an object: {0}".FormatWith(
CultureInfo.InvariantCulture, reader.TokenType));
JObject o = new JObject();
o.SetLineInfo(reader as IJsonLineInfo);
if (!reader.Read())
throw new Exception("Error reading JObject from JsonReader.");
JObject o = new JObject();
o.ReadContentFrom(reader);
return o;
+1
View File
@@ -186,6 +186,7 @@ namespace Newtonsoft.Json.Linq
CultureInfo.InvariantCulture, reader.TokenType));
JProperty p = new JProperty((string)reader.Value);
p.SetLineInfo(reader as IJsonLineInfo);
if (!reader.Read())
throw new Exception("Error reading JProperty from JsonReader.");
+33 -1
View File
@@ -38,12 +38,15 @@ namespace Newtonsoft.Json.Linq
/// <summary>
/// Represents an abstract JSON token.
/// </summary>
public abstract class JToken : IJEnumerable<JToken>
public abstract class JToken : IJEnumerable<JToken>, IJsonLineInfo
{
private JContainer _parent;
internal JToken _next;
private static JTokenEqualityComparer _equalityComparer;
private int? _lineNumber;
private int? _linePosition;
/// <summary>
/// Gets a comparer that can compare two tokens for value equality.
/// </summary>
@@ -797,5 +800,34 @@ namespace Newtonsoft.Json.Linq
// TODO: loading constructor and parameters?
throw new Exception("Error reading JToken from JsonReader. Unexpected token: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
}
internal void SetLineInfo(IJsonLineInfo lineInfo)
{
if (lineInfo == null || !lineInfo.HasLineInfo())
return;
SetLineInfo(lineInfo.LineNumber, lineInfo.LinePosition);
}
internal void SetLineInfo(int lineNumber, int linePosition)
{
_lineNumber = lineNumber;
_linePosition = linePosition;
}
bool IJsonLineInfo.HasLineInfo()
{
return (_lineNumber != null && _linePosition != null);
}
int IJsonLineInfo.LineNumber
{
get { return _lineNumber ?? 0; }
}
int IJsonLineInfo.LinePosition
{
get { return _linePosition ?? 0; }
}
}
}
+45 -1
View File
@@ -9,7 +9,7 @@ namespace Newtonsoft.Json.Linq
/// <summary>
/// Represents a reader that provides fast, non-cached, forward-only access to serialized Json data.
/// </summary>
public class JsonTokenReader : JsonReader
public class JsonTokenReader : JsonReader, IJsonLineInfo
{
private readonly JToken _root;
private JToken _parent;
@@ -75,6 +75,11 @@ namespace Newtonsoft.Json.Linq
return false;
}
private bool IsEndElement
{
get { return (_current == _parent); }
}
private JsonToken? GetEndToken(JContainer c)
{
switch (c.Type)
@@ -171,5 +176,44 @@ namespace Newtonsoft.Json.Linq
throw MiscellaneousUtils.CreateArgumentOutOfRangeException("Type", token.Type, "Unexpected JsonTokenType.");
}
}
bool IJsonLineInfo.HasLineInfo()
{
if (CurrentState == State.Start)
return false;
IJsonLineInfo info = IsEndElement ? null : _current;
return (info != null && info.HasLineInfo());
}
int IJsonLineInfo.LineNumber
{
get
{
if (CurrentState == State.Start)
return 0;
IJsonLineInfo info = IsEndElement ? null : _current;
if (info != null)
return info.LineNumber;
return 0;
}
}
int IJsonLineInfo.LinePosition
{
get
{
if (CurrentState == State.Start)
return 0;
IJsonLineInfo info = IsEndElement ? null : _current;
if (info != null)
return info.LinePosition;
return 0;
}
}
}
}
@@ -56,6 +56,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="DateTimeOffset.cs" />
<Compile Include="IJsonLineInfo.cs" />
<Compile Include="JsonArrayAttribute.cs" />
<Compile Include="JsonContainerAttribute.cs" />
<Compile Include="DefaultValueHandling.cs" />
@@ -55,6 +55,7 @@
<Compile Include="Converters\HtmlColorConverter.cs" />
<Compile Include="DateTimeOffset.cs" />
<Compile Include="DefaultValueHandling.cs" />
<Compile Include="IJsonLineInfo.cs" />
<Compile Include="JsonArrayAttribute.cs" />
<Compile Include="JsonContainerAttribute.cs" />
<Compile Include="JsonConvert.cs" />
@@ -74,6 +74,7 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="IJsonLineInfo.cs" />
<Compile Include="JsonArrayAttribute.cs" />
<Compile Include="JsonContainerAttribute.cs" />
<Compile Include="DefaultValueHandling.cs" />
@@ -32,6 +32,9 @@ namespace Newtonsoft.Json.Schema
/// </summary>
public class JsonSchemaException : Exception
{
public int LineNumber { get; private set; }
public int LinePosition { get; private set; }
/// <summary>
/// Initializes a new instance of the <see cref="JsonSchemaException"/> class.
/// </summary>
@@ -59,5 +62,12 @@ namespace Newtonsoft.Json.Schema
: base(message, innerException)
{
}
internal JsonSchemaException(string message, Exception innerException, int lineNumber, int linePosition)
: base(message, innerException)
{
LineNumber = lineNumber;
LinePosition = linePosition;
}
}
}
@@ -253,8 +253,11 @@ namespace Newtonsoft.Json.Schema
CurrentSchema.Properties.Add(mapping.MappingName, propertySchema);
}
}
if (type.IsSealed)
CurrentSchema.AllowAdditionalProperties = false;
}
else if (CurrentSchema.Type == JsonSchemaType.Integer && type.IsEnum)
else if (CurrentSchema.Type == JsonSchemaType.Integer && type.IsEnum && !type.IsDefined(typeof(FlagsAttribute), true))
{
CurrentSchema.Enum = new List<JToken>();
CurrentSchema.Options = new Dictionary<JToken, string>();
+14 -2
View File
@@ -59,11 +59,14 @@ namespace Newtonsoft.Json.Utilities
if (initialType == typeof(Guid) && (targetType == typeof(Guid) || targetType == typeof(string)))
return true;
if (initialType == typeof(Type) && targetType == typeof(string))
return true;
#if !PocketPC
// see if source or target types have a TypeConverter that converts between the two
TypeConverter toConverter = GetConverter(initialType);
if (toConverter != null && toConverter.CanConvertTo(targetType))
if (toConverter != null && !IsComponentConverter(toConverter) && toConverter.CanConvertTo(targetType))
{
if (allowTypeNameToString || toConverter.GetType() != typeof(TypeConverter))
return true;
@@ -71,7 +74,7 @@ namespace Newtonsoft.Json.Utilities
TypeConverter fromConverter = GetConverter(targetType);
if (fromConverter != null && fromConverter.CanConvertFrom(initialType))
if (fromConverter != null && !IsComponentConverter(fromConverter) && fromConverter.CanConvertFrom(initialType))
return true;
#endif
@@ -85,6 +88,15 @@ namespace Newtonsoft.Json.Utilities
return false;
}
private static bool IsComponentConverter(TypeConverter converter)
{
#if !SILVERLIGHT && !PocketPC
return (converter is ComponentConverter);
#else
return false;
#endif
}
#region Convert
/// <summary>
/// Converts the value to the specified type.
@@ -231,7 +231,7 @@ namespace Newtonsoft.Json.Utilities
return genericListType.GetGenericArguments()[0];
}
else if (typeof(IList).IsAssignableFrom(type))
else if (typeof(ICollection).IsAssignableFrom(type))
{
return null;
}