-Added Path to JsonReader/JsonWriter/ErrorContext with the JSON path of the current position

-Changed collection type on JsonArrayContract to public
-Changed dictionary key type and dictionary value type on JsonDictionaryContract to public
-Fixed error handling when failing to parse array content
-Fixed error handling when there are missing required properties
This commit is contained in:
James Newton-King
2012-02-23 23:07:41 +13:00
parent 4f8832adc0
commit 0d6ad0b76e
14 changed files with 764 additions and 262 deletions
+102 -50
View File
@@ -272,75 +272,127 @@ namespace Newtonsoft.Json.Tests
{
string input = @"{
value:'Purple',
array:[1,2],
subobject:{prop:1}
array:[1,2,new Date(1)],
subobject:{prop:1,proparray:[1]}
}";
StringReader sr = new StringReader(input);
using (JsonReader jsonReader = new JsonTextReader(sr))
using (JsonReader reader = new JsonTextReader(sr))
{
Assert.AreEqual(0, jsonReader.Depth);
Assert.AreEqual(0, reader.Depth);
jsonReader.Read();
Assert.AreEqual(jsonReader.TokenType, JsonToken.StartObject);
Assert.AreEqual(0, jsonReader.Depth);
reader.Read();
Assert.AreEqual(reader.TokenType, JsonToken.StartObject);
Assert.AreEqual(0, reader.Depth);
Assert.AreEqual("", reader.Path);
jsonReader.Read();
Assert.AreEqual(jsonReader.TokenType, JsonToken.PropertyName);
Assert.AreEqual(1, jsonReader.Depth);
reader.Read();
Assert.AreEqual(reader.TokenType, JsonToken.PropertyName);
Assert.AreEqual(1, reader.Depth);
Assert.AreEqual("value", reader.Path);
jsonReader.Read();
Assert.AreEqual(jsonReader.TokenType, JsonToken.String);
Assert.AreEqual(jsonReader.Value, @"Purple");
Assert.AreEqual(jsonReader.QuoteChar, '\'');
Assert.AreEqual(1, jsonReader.Depth);
reader.Read();
Assert.AreEqual(reader.TokenType, JsonToken.String);
Assert.AreEqual(reader.Value, @"Purple");
Assert.AreEqual(reader.QuoteChar, '\'');
Assert.AreEqual(1, reader.Depth);
Assert.AreEqual("value", reader.Path);
jsonReader.Read();
Assert.AreEqual(jsonReader.TokenType, JsonToken.PropertyName);
Assert.AreEqual(1, jsonReader.Depth);
reader.Read();
Assert.AreEqual(reader.TokenType, JsonToken.PropertyName);
Assert.AreEqual(1, reader.Depth);
Assert.AreEqual("array", reader.Path);
jsonReader.Read();
Assert.AreEqual(jsonReader.TokenType, JsonToken.StartArray);
Assert.AreEqual(1, jsonReader.Depth);
reader.Read();
Assert.AreEqual(reader.TokenType, JsonToken.StartArray);
Assert.AreEqual(1, reader.Depth);
Assert.AreEqual("array", reader.Path);
jsonReader.Read();
Assert.AreEqual(jsonReader.TokenType, JsonToken.Integer);
Assert.AreEqual(1, jsonReader.Value);
Assert.AreEqual(2, jsonReader.Depth);
reader.Read();
Assert.AreEqual(reader.TokenType, JsonToken.Integer);
Assert.AreEqual(1, reader.Value);
Assert.AreEqual(2, reader.Depth);
Assert.AreEqual("array[0]", reader.Path);
jsonReader.Read();
Assert.AreEqual(jsonReader.TokenType, JsonToken.Integer);
Assert.AreEqual(2, jsonReader.Value);
Assert.AreEqual(2, jsonReader.Depth);
reader.Read();
Assert.AreEqual(reader.TokenType, JsonToken.Integer);
Assert.AreEqual(2, reader.Value);
Assert.AreEqual(2, reader.Depth);
Assert.AreEqual("array[1]", reader.Path);
jsonReader.Read();
Assert.AreEqual(jsonReader.TokenType, JsonToken.EndArray);
Assert.AreEqual(1, jsonReader.Depth);
reader.Read();
Assert.AreEqual(reader.TokenType, JsonToken.StartConstructor);
Assert.AreEqual("Date", reader.Value);
Assert.AreEqual(2, reader.Depth);
Assert.AreEqual("array[2]", reader.Path);
jsonReader.Read();
Assert.AreEqual(jsonReader.TokenType, JsonToken.PropertyName);
Assert.AreEqual(1, jsonReader.Depth);
reader.Read();
Assert.AreEqual(reader.TokenType, JsonToken.Integer);
Assert.AreEqual(1, reader.Value);
Assert.AreEqual(3, reader.Depth);
Assert.AreEqual("array[2][0]", reader.Path);
jsonReader.Read();
Assert.AreEqual(jsonReader.TokenType, JsonToken.StartObject);
Assert.AreEqual(1, jsonReader.Depth);
reader.Read();
Assert.AreEqual(reader.TokenType, JsonToken.EndConstructor);
Assert.AreEqual(null, reader.Value);
Assert.AreEqual(2, reader.Depth);
Assert.AreEqual("array[2]", reader.Path);
jsonReader.Read();
Assert.AreEqual(jsonReader.TokenType, JsonToken.PropertyName);
Assert.AreEqual(2, jsonReader.Depth);
reader.Read();
Assert.AreEqual(reader.TokenType, JsonToken.EndArray);
Assert.AreEqual(1, reader.Depth);
Assert.AreEqual("array", reader.Path);
jsonReader.Read();
Assert.AreEqual(jsonReader.TokenType, JsonToken.Integer);
Assert.AreEqual(2, jsonReader.Depth);
reader.Read();
Assert.AreEqual(reader.TokenType, JsonToken.PropertyName);
Assert.AreEqual(1, reader.Depth);
Assert.AreEqual("subobject", reader.Path);
jsonReader.Read();
Assert.AreEqual(jsonReader.TokenType, JsonToken.EndObject);
Assert.AreEqual(1, jsonReader.Depth);
reader.Read();
Assert.AreEqual(reader.TokenType, JsonToken.StartObject);
Assert.AreEqual(1, reader.Depth);
Assert.AreEqual("subobject", reader.Path);
jsonReader.Read();
Assert.AreEqual(jsonReader.TokenType, JsonToken.EndObject);
Assert.AreEqual(0, jsonReader.Depth);
reader.Read();
Assert.AreEqual(reader.TokenType, JsonToken.PropertyName);
Assert.AreEqual(2, reader.Depth);
Assert.AreEqual("subobject.prop", reader.Path);
reader.Read();
Assert.AreEqual(reader.TokenType, JsonToken.Integer);
Assert.AreEqual(2, reader.Depth);
Assert.AreEqual("subobject.prop", reader.Path);
reader.Read();
Assert.AreEqual(reader.TokenType, JsonToken.PropertyName);
Assert.AreEqual(2, reader.Depth);
Assert.AreEqual("subobject.proparray", reader.Path);
reader.Read();
Assert.AreEqual(reader.TokenType, JsonToken.StartArray);
Assert.AreEqual(2, reader.Depth);
Assert.AreEqual("subobject.proparray", reader.Path);
reader.Read();
Assert.AreEqual(reader.TokenType, JsonToken.Integer);
Assert.AreEqual(3, reader.Depth);
Assert.AreEqual("subobject.proparray[0]", reader.Path);
reader.Read();
Assert.AreEqual(reader.TokenType, JsonToken.EndArray);
Assert.AreEqual(2, reader.Depth);
Assert.AreEqual("subobject.proparray", reader.Path);
reader.Read();
Assert.AreEqual(reader.TokenType, JsonToken.EndObject);
Assert.AreEqual(1, reader.Depth);
Assert.AreEqual("subobject", reader.Path);
reader.Read();
Assert.AreEqual(reader.TokenType, JsonToken.EndObject);
Assert.AreEqual(0, reader.Depth);
Assert.AreEqual("", reader.Path);
}
}
+160 -3
View File
@@ -199,6 +199,85 @@ namespace Newtonsoft.Json.Tests
Assert.AreEqual(expected, result);
}
[Test]
public void WriteEnd()
{
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
using (JsonWriter jsonWriter = new JsonTextWriter(sw))
{
jsonWriter.Formatting = Formatting.Indented;
jsonWriter.WriteStartObject();
jsonWriter.WritePropertyName("CPU");
jsonWriter.WriteValue("Intel");
jsonWriter.WritePropertyName("PSU");
jsonWriter.WriteValue("500W");
jsonWriter.WritePropertyName("Drives");
jsonWriter.WriteStartArray();
jsonWriter.WriteValue("DVD read/writer");
jsonWriter.WriteComment("(broken)");
jsonWriter.WriteValue("500 gigabyte hard drive");
jsonWriter.WriteValue("200 gigabype hard drive");
jsonWriter.WriteEndObject();
Assert.AreEqual(WriteState.Start, jsonWriter.WriteState);
}
string expected = @"{
""CPU"": ""Intel"",
""PSU"": ""500W"",
""Drives"": [
""DVD read/writer""
/*(broken)*/,
""500 gigabyte hard drive"",
""200 gigabype hard drive""
]
}";
string result = sb.ToString();
Assert.AreEqual(expected, result);
}
[Test]
public void CloseWithRemainingContent()
{
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
using (JsonWriter jsonWriter = new JsonTextWriter(sw))
{
jsonWriter.Formatting = Formatting.Indented;
jsonWriter.WriteStartObject();
jsonWriter.WritePropertyName("CPU");
jsonWriter.WriteValue("Intel");
jsonWriter.WritePropertyName("PSU");
jsonWriter.WriteValue("500W");
jsonWriter.WritePropertyName("Drives");
jsonWriter.WriteStartArray();
jsonWriter.WriteValue("DVD read/writer");
jsonWriter.WriteComment("(broken)");
jsonWriter.WriteValue("500 gigabyte hard drive");
jsonWriter.WriteValue("200 gigabype hard drive");
jsonWriter.Close();
}
string expected = @"{
""CPU"": ""Intel"",
""PSU"": ""500W"",
""Drives"": [
""DVD read/writer""
/*(broken)*/,
""500 gigabyte hard drive"",
""200 gigabype hard drive""
]
}";
string result = sb.ToString();
Assert.AreEqual(expected, result);
}
[Test]
public void Indenting()
{
@@ -222,6 +301,7 @@ namespace Newtonsoft.Json.Tests
jsonWriter.WriteValue("200 gigabype hard drive");
jsonWriter.WriteEnd();
jsonWriter.WriteEndObject();
Assert.AreEqual(WriteState.Start, jsonWriter.WriteState);
}
// {
@@ -247,9 +327,6 @@ namespace Newtonsoft.Json.Tests
}";
string result = sb.ToString();
Console.WriteLine("Indenting");
Console.WriteLine(result);
Assert.AreEqual(expected, result);
}
@@ -265,27 +342,34 @@ namespace Newtonsoft.Json.Tests
jsonWriter.WriteStartObject();
Assert.AreEqual(WriteState.Object, jsonWriter.WriteState);
Assert.AreEqual("", jsonWriter.Path);
jsonWriter.WritePropertyName("CPU");
Assert.AreEqual(WriteState.Property, jsonWriter.WriteState);
Assert.AreEqual("CPU", jsonWriter.Path);
jsonWriter.WriteValue("Intel");
Assert.AreEqual(WriteState.Object, jsonWriter.WriteState);
Assert.AreEqual("CPU", jsonWriter.Path);
jsonWriter.WritePropertyName("Drives");
Assert.AreEqual(WriteState.Property, jsonWriter.WriteState);
Assert.AreEqual("Drives", jsonWriter.Path);
jsonWriter.WriteStartArray();
Assert.AreEqual(WriteState.Array, jsonWriter.WriteState);
jsonWriter.WriteValue("DVD read/writer");
Assert.AreEqual(WriteState.Array, jsonWriter.WriteState);
Assert.AreEqual("Drives[0]", jsonWriter.Path);
jsonWriter.WriteEnd();
Assert.AreEqual(WriteState.Object, jsonWriter.WriteState);
Assert.AreEqual("Drives", jsonWriter.Path);
jsonWriter.WriteEndObject();
Assert.AreEqual(WriteState.Start, jsonWriter.WriteState);
Assert.AreEqual("", jsonWriter.Path);
}
}
@@ -620,6 +704,79 @@ _____'propertyName': NaN
Assert.AreEqual(expected, result);
}
[Test]
public void Path()
{
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
string text = "Hello world.";
byte[] data = Encoding.UTF8.GetBytes(text);
using (JsonTextWriter writer = new JsonTextWriter(sw))
{
writer.Formatting = Formatting.Indented;
writer.WriteStartArray();
Assert.AreEqual("", writer.Path);
writer.WriteStartObject();
Assert.AreEqual("[0]", writer.Path);
writer.WritePropertyName("Property1");
Assert.AreEqual("[0].Property1", writer.Path);
writer.WriteStartArray();
Assert.AreEqual("[0].Property1", writer.Path);
writer.WriteValue(1);
Assert.AreEqual("[0].Property1[0]", writer.Path);
writer.WriteStartArray();
Assert.AreEqual("[0].Property1[1]", writer.Path);
writer.WriteStartArray();
Assert.AreEqual("[0].Property1[1][0]", writer.Path);
writer.WriteStartArray();
Assert.AreEqual("[0].Property1[1][0][0]", writer.Path);
writer.WriteEndObject();
Assert.AreEqual("[0]", writer.Path);
writer.WriteStartObject();
Assert.AreEqual("[1]", writer.Path);
writer.WritePropertyName("Property2");
Assert.AreEqual("[1].Property2", writer.Path);
writer.WriteStartConstructor("Constructor1");
Assert.AreEqual("[1].Property2", writer.Path);
writer.WriteNull();
Assert.AreEqual("[1].Property2[0]", writer.Path);
writer.WriteStartArray();
Assert.AreEqual("[1].Property2[1]", writer.Path);
writer.WriteValue(1);
Assert.AreEqual("[1].Property2[1][0]", writer.Path);
writer.WriteEnd();
Assert.AreEqual("[1].Property2[1]", writer.Path);
writer.WriteEndObject();
Assert.AreEqual("[1]", writer.Path);
writer.WriteEndArray();
Assert.AreEqual("", writer.Path);
}
Assert.AreEqual(@"[
{
""Property1"": [
1,
[
[
[]
]
]
]
},
{
""Property2"": new Constructor1(
null,
[
1
]
)
}
]", sb.ToString());
}
[Test]
public void BuildStateArray()
{
@@ -72,5 +72,5 @@ using System.Security;
// by using the '*' as shown below:
[assembly: AssemblyVersion("4.0.8.0")]
#if !PocketPC
[assembly: AssemblyFileVersion("4.0.8.14618")]
[assembly: AssemblyFileVersion("4.0.8.14623")]
#endif
@@ -57,7 +57,7 @@ namespace Newtonsoft.Json.Tests.Serialization
VersionKeyedCollection c = JsonConvert.DeserializeObject<VersionKeyedCollection>(json);
Assert.AreEqual(1, c.Count);
Assert.AreEqual(1, c.Messages.Count);
Assert.AreEqual("Error message for member 1 = An item with the same key has already been added.", c.Messages[0]);
Assert.AreEqual("[1] - Error message for member 1 = An item with the same key has already been added.", c.Messages[0]);
}
[Test]
@@ -161,7 +161,8 @@ namespace Newtonsoft.Json.Tests.Serialization
{
List<string> errors = new List<string>();
List<DateTime> c = JsonConvert.DeserializeObject<List<DateTime>>(@"[
List<DateTime> c = JsonConvert.DeserializeObject<List<DateTime>>(
@"[
""2009-09-09T00:00:00Z"",
""I am not a date and will error!"",
[
@@ -175,10 +176,10 @@ namespace Newtonsoft.Json.Tests.Serialization
{
Error = delegate(object sender, ErrorEventArgs args)
{
errors.Add(args.ErrorContext.Error.Message);
errors.Add(args.ErrorContext.Path + " - " + args.ErrorContext.Member + " - " + args.ErrorContext.Error.Message);
args.ErrorContext.Handled = true;
},
Converters = { new IsoDateTimeConverter() }
Converters = {new IsoDateTimeConverter()}
});
// 2009-09-09T00:00:00Z
@@ -196,12 +197,12 @@ namespace Newtonsoft.Json.Tests.Serialization
Assert.AreEqual(3, errors.Count);
#if !(NET20 || NET35 || WINDOWS_PHONE)
Assert.AreEqual("The string was not recognized as a valid DateTime. There is an unknown word starting at index 0.", errors[0]);
Assert.AreEqual("[1] - 1 - The string was not recognized as a valid DateTime. There is an unknown word starting at index 0.", errors[0]);
#else
Assert.AreEqual("The string was not recognized as a valid DateTime. There is a unknown word starting at index 0.", errors[0]);
Assert.AreEqual("[1] - 1 - The string was not recognized as a valid DateTime. There is a unknown word starting at index 0.", errors[0]);
#endif
Assert.AreEqual("Unexpected token parsing date. Expected String, got StartArray.", errors[1]);
Assert.AreEqual("Cannot convert null value to System.DateTime.", errors[2]);
Assert.AreEqual("[2] - 2 - Unexpected token parsing date. Expected String, got StartArray.", errors[1]);
Assert.AreEqual("[4] - 4 - Cannot convert null value to System.DateTime.", errors[2]);
}
[Test]
@@ -209,7 +210,8 @@ namespace Newtonsoft.Json.Tests.Serialization
{
bool eventErrorHandlerCalled = false;
DateTimeErrorObjectCollection c = JsonConvert.DeserializeObject<DateTimeErrorObjectCollection>(@"[
DateTimeErrorObjectCollection c = JsonConvert.DeserializeObject<DateTimeErrorObjectCollection>(
@"[
""2009-09-09T00:00:00Z"",
""kjhkjhkjhkjh"",
[
@@ -220,13 +222,13 @@ namespace Newtonsoft.Json.Tests.Serialization
""2000-12-01T00:00:00Z""
]",
new JsonSerializerSettings
{
Error = (s, a) => eventErrorHandlerCalled = true,
Converters =
{
Error = (s, a) => eventErrorHandlerCalled = true,
Converters =
{
new IsoDateTimeConverter()
}
});
});
Assert.AreEqual(3, c.Count);
Assert.AreEqual(new DateTime(2009, 9, 9, 0, 0, 0, DateTimeKind.Utc), c[0]);
@@ -270,25 +272,76 @@ namespace Newtonsoft.Json.Tests.Serialization
string json = @"[[""kjhkjhkjhkjh""]]";
Exception e = null;
try
{
JsonSerializer serializer = new JsonSerializer();
serializer.Error += delegate(object sender, ErrorEventArgs args)
{
// only log an error once
if (args.CurrentObject == args.ErrorContext.OriginalObject)
errors.Add(args.ErrorContext.Error.Message);
};
{
// only log an error once
if (args.CurrentObject == args.ErrorContext.OriginalObject)
errors.Add(args.ErrorContext.Path + " - " + args.ErrorContext.Member + " - " + args.ErrorContext.Error.Message);
};
serializer.Deserialize(new StringReader(json), typeof(List<List<DateTime>>));
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
e = ex;
}
Assert.AreEqual(@"Error converting value ""kjhkjhkjhkjh"" to type 'System.DateTime'. Line 1, position 16.", e.Message);
Assert.AreEqual(1, errors.Count);
Assert.AreEqual(@"Error converting value ""kjhkjhkjhkjh"" to type 'System.DateTime'. Line 1, position 16.", errors[0]);
Assert.AreEqual(@"[0][0] - 0 - Error converting value ""kjhkjhkjhkjh"" to type 'System.DateTime'. Line 1, position 16.", errors[0]);
}
[Test]
public void MultipleRequiredPropertyErrors()
{
string json = "{}";
List<string> errors = new List<string>();
JsonSerializer serializer = new JsonSerializer();
serializer.Error += delegate(object sender, ErrorEventArgs args)
{
errors.Add(args.ErrorContext.Path + " - " + args.ErrorContext.Member + " - " + args.ErrorContext.Error.Message);
args.ErrorContext.Handled = true;
};
serializer.Deserialize(new JsonTextReader(new StringReader(json)), typeof (MyTypeWithRequiredMembers));
Assert.AreEqual(2, errors.Count);
Assert.AreEqual(" - Required1 - Required property 'Required1' not found in JSON. Line 1, position 2.", errors[0]);
Assert.AreEqual(" - Required2 - Required property 'Required2' not found in JSON. Line 1, position 2.", errors[1]);
}
[Test]
public void HandlingArrayErrors()
{
string json = "[\"a\",\"b\",\"45\",34]";
List<string> errors = new List<string>();
JsonSerializer serializer = new JsonSerializer();
serializer.Error += delegate(object sender, ErrorEventArgs args)
{
errors.Add(args.ErrorContext.Path + " - " + args.ErrorContext.Member + " - " + args.ErrorContext.Error.Message);
args.ErrorContext.Handled = true;
};
serializer.Deserialize(new JsonTextReader(new StringReader(json)), typeof(int[]));
Assert.AreEqual(2, errors.Count);
Assert.AreEqual("[0] - 0 - Could not convert string to integer: a. Line 1, position 4.", errors[0]);
Assert.AreEqual("[1] - 1 - Could not convert string to integer: b. Line 1, position 8.", errors[1]);
}
}
[JsonObject]
public class MyTypeWithRequiredMembers
{
[JsonProperty(Required = Required.AllowNull)]
public string Required1;
[JsonProperty(Required = Required.AllowNull)]
public string Required2;
}
}
@@ -50,7 +50,7 @@ namespace Newtonsoft.Json.Tests.TestObjects
[OnError]
internal void OnErrorMethod(StreamingContext context, ErrorContext errorContext)
{
Messages.Add("Error message for member " + errorContext.Member + " = " + errorContext.Error.Message);
Messages.Add(errorContext.Path + " - Error message for member " + errorContext.Member + " = " + errorContext.Error.Message);
errorContext.Handled = true;
}
+155 -42
View File
@@ -27,11 +27,78 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Globalization;
using System.Linq;
using System.Text;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Utilities;
namespace Newtonsoft.Json
{
internal enum JsonContainerType
{
None,
Object,
Array,
Constructor
}
internal struct JsonPosition
{
internal JsonContainerType Type;
internal int? Position;
internal string PropertyName;
internal void WriteTo(StringBuilder sb)
{
switch (Type)
{
case JsonContainerType.Object:
if (PropertyName != null)
{
if (sb.Length > 0)
sb.Append(".");
sb.Append(PropertyName);
}
break;
case JsonContainerType.Array:
case JsonContainerType.Constructor:
if (Position != null)
{
sb.Append("[");
sb.Append(Position);
sb.Append("]");
}
break;
}
}
internal bool InsideContainer()
{
switch (Type)
{
case JsonContainerType.Object:
return (PropertyName != null);
case JsonContainerType.Array:
case JsonContainerType.Constructor:
return (Position != null);
}
return false;
}
internal static string BuildPath(IEnumerable<JsonPosition> positions)
{
StringBuilder sb = new StringBuilder();
foreach (JsonPosition state in positions)
{
state.WriteTo(sb);
}
return sb.ToString();
}
}
/// <summary>
/// Represents a reader that provides fast, non-cached, forward-only access to serialized Json data.
/// </summary>
@@ -101,7 +168,7 @@ namespace Newtonsoft.Json
private object _value;
private char _quoteChar;
internal State _currentState;
private JTokenType _currentTypeContext;
private JsonPosition _currentPosition;
private CultureInfo _culture;
/// <summary>
@@ -113,9 +180,7 @@ namespace Newtonsoft.Json
get { return _currentState; }
}
private int _top;
private readonly List<JTokenType> _stack;
private readonly List<JsonPosition> _stack;
/// <summary>
/// Gets or sets a value indicating whether the underlying stream or
@@ -137,7 +202,7 @@ namespace Newtonsoft.Json
}
/// <summary>
/// Gets the type of the current Json token.
/// Gets the type of the current JSON token.
/// </summary>
public virtual JsonToken TokenType
{
@@ -145,7 +210,7 @@ namespace Newtonsoft.Json
}
/// <summary>
/// Gets the text value of the current Json token.
/// Gets the text value of the current JSON token.
/// </summary>
public virtual object Value
{
@@ -153,7 +218,7 @@ namespace Newtonsoft.Json
}
/// <summary>
/// Gets The Common Language Runtime (CLR) type for the current Json token.
/// Gets The Common Language Runtime (CLR) type for the current JSON token.
/// </summary>
public virtual Type ValueType
{
@@ -168,11 +233,11 @@ namespace Newtonsoft.Json
{
get
{
int depth = _top - 1;
if (IsStartToken(TokenType))
return depth - 1;
else
int depth = _stack.Count;
if (IsStartToken(TokenType) || _currentPosition.Type == JsonContainerType.None)
return depth;
else
return depth + 1;
}
}
@@ -185,39 +250,71 @@ namespace Newtonsoft.Json
set { _culture = value; }
}
/// <summary>
/// Gets the path of the current JSON token.
/// </summary>
public string Path
{
get
{
if (_currentPosition.Type == JsonContainerType.None)
return string.Empty;
return JsonPosition.BuildPath(_stack.Concat(new[] { _currentPosition }));
}
}
/// <summary>
/// Initializes a new instance of the <see cref="JsonReader"/> class with the specified <see cref="TextReader"/>.
/// </summary>
protected JsonReader()
{
_currentState = State.Start;
_stack = new List<JTokenType>();
_stack = new List<JsonPosition>(4);
CloseInput = true;
Push(JTokenType.None);
}
private void Push(JTokenType value)
private void Push(JsonContainerType value)
{
_stack.Add(value);
_top++;
_currentTypeContext = value;
UpdateScopeWithFinishedValue();
if (_currentPosition.Type == JsonContainerType.None)
{
_currentPosition.Type = value;
}
else
{
_stack.Add(_currentPosition);
var state = new JsonPosition
{
Type = value
};
_currentPosition = state;
}
}
private JTokenType Pop()
private JsonContainerType Pop()
{
JTokenType value = Peek();
_stack.RemoveAt(_stack.Count - 1);
_top--;
_currentTypeContext = _stack[_top - 1];
JsonPosition oldPosition;
if (_stack.Count > 0)
{
oldPosition = _currentPosition;
_currentPosition = _stack[_stack.Count - 1];
_stack.RemoveAt(_stack.Count - 1);
}
else
{
oldPosition = _currentPosition;
_currentPosition = new JsonPosition();
}
return value;
return oldPosition.Type;
}
private JTokenType Peek()
private JsonContainerType Peek()
{
return _currentTypeContext;
return _currentPosition.Type;
}
/// <summary>
@@ -292,15 +389,15 @@ namespace Newtonsoft.Json
{
case JsonToken.StartObject:
_currentState = State.ObjectStart;
Push(JTokenType.Object);
Push(JsonContainerType.Object);
break;
case JsonToken.StartArray:
_currentState = State.ArrayStart;
Push(JTokenType.Array);
Push(JsonContainerType.Array);
break;
case JsonToken.StartConstructor:
_currentState = State.ConstructorStart;
Push(JTokenType.Constructor);
Push(JsonContainerType.Constructor);
break;
case JsonToken.EndObject:
ValidateEnd(JsonToken.EndObject);
@@ -313,6 +410,8 @@ namespace Newtonsoft.Json
break;
case JsonToken.PropertyName:
_currentState = State.Property;
_currentPosition.PropertyName = (string) value;
break;
case JsonToken.Undefined:
case JsonToken.Integer:
@@ -323,21 +422,35 @@ namespace Newtonsoft.Json
case JsonToken.String:
case JsonToken.Raw:
case JsonToken.Bytes:
_currentState = (Peek() != JTokenType.None) ? State.PostValue : State.Finished;
_currentState = (Peek() != JsonContainerType.None) ? State.PostValue : State.Finished;
UpdateScopeWithFinishedValue();
break;
}
_value = value;
}
private void UpdateScopeWithFinishedValue()
{
if (_currentPosition.Type == JsonContainerType.Array
|| _currentPosition.Type == JsonContainerType.Constructor)
{
if (_currentPosition.Position == null)
_currentPosition.Position = 0;
else
_currentPosition.Position++;
}
}
private void ValidateEnd(JsonToken endToken)
{
JTokenType currentObject = Pop();
JsonContainerType currentObject = Pop();
if (GetTypeForCloseToken(endToken) != currentObject)
throw new JsonReaderException("JsonToken {0} is not valid for closing JsonType {1}.".FormatWith(CultureInfo.InvariantCulture, endToken, currentObject));
_currentState = (Peek() != JTokenType.None) ? State.PostValue : State.Finished;
_currentState = (Peek() != JsonContainerType.None) ? State.PostValue : State.Finished;
}
/// <summary>
@@ -345,20 +458,20 @@ namespace Newtonsoft.Json
/// </summary>
protected void SetStateBasedOnCurrent()
{
JTokenType currentObject = Peek();
JsonContainerType currentObject = Peek();
switch (currentObject)
{
case JTokenType.Object:
case JsonContainerType.Object:
_currentState = State.Object;
break;
case JTokenType.Array:
case JsonContainerType.Array:
_currentState = State.Array;
break;
case JTokenType.Constructor:
case JsonContainerType.Constructor:
_currentState = State.Constructor;
break;
case JTokenType.None:
case JsonContainerType.None:
_currentState = State.Finished;
break;
default:
@@ -413,16 +526,16 @@ namespace Newtonsoft.Json
}
}
private JTokenType GetTypeForCloseToken(JsonToken token)
private JsonContainerType GetTypeForCloseToken(JsonToken token)
{
switch (token)
{
case JsonToken.EndObject:
return JTokenType.Object;
return JsonContainerType.Object;
case JsonToken.EndArray:
return JTokenType.Array;
return JsonContainerType.Array;
case JsonToken.EndConstructor:
return JTokenType.Constructor;
return JsonContainerType.Constructor;
default:
throw new JsonReaderException("Not a valid close JsonToken: {0}".FormatWith(CultureInfo.InvariantCulture, token));
}
@@ -497,4 +610,4 @@ namespace Newtonsoft.Json
return message;
}
}
}
}
+140 -57
View File
@@ -160,9 +160,8 @@ namespace Newtonsoft.Json
StateArray = BuildStateArray();
}
private int _top;
private readonly List<JTokenType> _stack;
private readonly List<JsonPosition> _stack;
private JsonPosition _currentPosition;
private State _currentState;
private Formatting _formatting;
@@ -182,9 +181,31 @@ namespace Newtonsoft.Json
/// <value>The top.</value>
protected internal int Top
{
get { return _top; }
get
{
int depth = _stack.Count;
if (Peek() != JsonContainerType.None)
depth++;
return depth;
}
}
internal string ContainerPath
{
get
{
if (_currentPosition.Type == JsonContainerType.None)
return string.Empty;
IEnumerable<JsonPosition> positions = (_currentPosition.InsideContainer())
? _stack
: _stack.Concat(new[] { _currentPosition });
return JsonPosition.BuildPath(positions);
}
}
/// <summary>
/// Gets the state of the writer.
/// </summary>
@@ -217,6 +238,20 @@ namespace Newtonsoft.Json
}
}
/// <summary>
/// Gets the path of the writer.
/// </summary>
public string Path
{
get
{
if (_currentPosition.Type == JsonContainerType.None)
return string.Empty;
return JsonPosition.BuildPath(_stack.Concat(new[] { _currentPosition }));
}
}
/// <summary>
/// Indicates how the output is formatted.
/// </summary>
@@ -231,34 +266,65 @@ namespace Newtonsoft.Json
/// </summary>
protected JsonWriter()
{
_stack = new List<JTokenType>(8);
_stack.Add(JTokenType.None);
_stack = new List<JsonPosition>(4);
_currentState = State.Start;
_formatting = Formatting.None;
CloseOutput = true;
}
private void Push(JTokenType value)
private void UpdateScopeWithFinishedValue()
{
_top++;
if (_stack.Count <= _top)
_stack.Add(value);
if (_currentPosition.Type == JsonContainerType.Array
|| _currentPosition.Type == JsonContainerType.Constructor)
{
if (_currentPosition.Position == null)
_currentPosition.Position = 0;
else
_currentPosition.Position++;
}
}
private void Push(JsonContainerType value)
{
UpdateScopeWithFinishedValue();
if (_currentPosition.Type == JsonContainerType.None)
{
_currentPosition.Type = value;
}
else
_stack[_top] = value;
{
_stack.Add(_currentPosition);
var state = new JsonPosition
{
Type = value
};
_currentPosition = state;
}
}
private JTokenType Pop()
private JsonContainerType Pop()
{
JTokenType value = Peek();
_top--;
JsonPosition oldPosition;
if (_stack.Count > 0)
{
oldPosition = _currentPosition;
_currentPosition = _stack[_stack.Count - 1];
_stack.RemoveAt(_stack.Count - 1);
}
else
{
oldPosition = _currentPosition;
_currentPosition = new JsonPosition();
}
return value;
return oldPosition.Type;
}
private JTokenType Peek()
private JsonContainerType Peek()
{
return _stack[_top];
return _currentPosition.Type;
}
/// <summary>
@@ -280,7 +346,7 @@ namespace Newtonsoft.Json
public virtual void WriteStartObject()
{
AutoComplete(JsonToken.StartObject);
Push(JTokenType.Object);
Push(JsonContainerType.Object);
}
/// <summary>
@@ -297,7 +363,7 @@ namespace Newtonsoft.Json
public virtual void WriteStartArray()
{
AutoComplete(JsonToken.StartArray);
Push(JTokenType.Array);
Push(JsonContainerType.Array);
}
/// <summary>
@@ -315,7 +381,7 @@ namespace Newtonsoft.Json
public virtual void WriteStartConstructor(string name)
{
AutoComplete(JsonToken.StartConstructor);
Push(JTokenType.Constructor);
Push(JsonContainerType.Constructor);
}
/// <summary>
@@ -332,6 +398,7 @@ namespace Newtonsoft.Json
/// <param name="name">The name of the property.</param>
public virtual void WritePropertyName(string name)
{
_currentPosition.PropertyName = name;
AutoComplete(JsonToken.PropertyName);
}
@@ -482,17 +549,17 @@ namespace Newtonsoft.Json
}
}
private void WriteEnd(JTokenType type)
private void WriteEnd(JsonContainerType type)
{
switch (type)
{
case JTokenType.Object:
case JsonContainerType.Object:
WriteEndObject();
break;
case JTokenType.Array:
case JsonContainerType.Array:
WriteEndArray();
break;
case JTokenType.Constructor:
case JsonContainerType.Constructor:
WriteEndConstructor();
break;
default:
@@ -502,36 +569,36 @@ namespace Newtonsoft.Json
private void AutoCompleteAll()
{
while (_top > 0)
while (Top > 0)
{
WriteEnd();
}
}
private JTokenType GetTypeForCloseToken(JsonToken token)
private JsonContainerType GetTypeForCloseToken(JsonToken token)
{
switch (token)
{
case JsonToken.EndObject:
return JTokenType.Object;
return JsonContainerType.Object;
case JsonToken.EndArray:
return JTokenType.Array;
return JsonContainerType.Array;
case JsonToken.EndConstructor:
return JTokenType.Constructor;
return JsonContainerType.Constructor;
default:
throw new JsonWriterException("No type for token: " + token);
}
}
private JsonToken GetCloseTokenForType(JTokenType type)
private JsonToken GetCloseTokenForType(JsonContainerType type)
{
switch (type)
{
case JTokenType.Object:
case JsonContainerType.Object:
return JsonToken.EndObject;
case JTokenType.Array:
case JsonContainerType.Array:
return JsonToken.EndArray;
case JTokenType.Constructor:
case JsonContainerType.Constructor:
return JsonToken.EndConstructor;
default:
throw new JsonWriterException("No close token for type: " + type);
@@ -543,15 +610,24 @@ namespace Newtonsoft.Json
// write closing symbol and calculate new state
int levelsToComplete = 0;
JsonContainerType type = GetTypeForCloseToken(tokenBeingClosed);
for (int i = 0; i < _top; i++)
if (_currentPosition.Type == type)
{
int currentLevel = _top - i;
if (_stack[currentLevel] == GetTypeForCloseToken(tokenBeingClosed))
levelsToComplete = 1;
}
else
{
int top = Top - 2;
for (int i = top; i >= 0; i--)
{
levelsToComplete = i + 1;
break;
int currentLevel = top - i;
if (_stack[currentLevel].Type == type)
{
levelsToComplete = i + 2;
break;
}
}
}
@@ -569,26 +645,26 @@ namespace Newtonsoft.Json
}
WriteEnd(token);
}
JTokenType currentLevelType = Peek();
JsonContainerType currentLevelType = Peek();
switch (currentLevelType)
{
case JTokenType.Object:
_currentState = State.Object;
break;
case JTokenType.Array:
_currentState = State.Array;
break;
case JTokenType.Constructor:
_currentState = State.Array;
break;
case JTokenType.None:
_currentState = State.Start;
break;
default:
throw new JsonWriterException("Unknown JsonType: " + currentLevelType);
switch (currentLevelType)
{
case JsonContainerType.Object:
_currentState = State.Object;
break;
case JsonContainerType.Array:
_currentState = State.Array;
break;
case JsonContainerType.Constructor:
_currentState = State.Array;
break;
case JsonContainerType.None:
_currentState = State.Start;
break;
default:
throw new JsonWriterException("Unknown JsonType: " + currentLevelType);
}
}
}
@@ -623,11 +699,18 @@ namespace Newtonsoft.Json
internal void AutoComplete(JsonToken tokenBeingWritten)
{
if (tokenBeingWritten != JsonToken.StartObject
&& tokenBeingWritten != JsonToken.StartArray
&& tokenBeingWritten != JsonToken.StartConstructor)
UpdateScopeWithFinishedValue();
// gets new state based on the current state and what is being written
State newState = StateArray[(int)tokenBeingWritten][(int)_currentState];
if (newState == State.Error)
{
throw new JsonWriterException("Token {0} in state {1} would result in an invalid JSON object.".FormatWith(CultureInfo.InvariantCulture, tokenBeingWritten.ToString(), _currentState.ToString()));
}
if ((_currentState == State.Object || _currentState == State.Array || _currentState == State.Constructor) && tokenBeingWritten != JsonToken.Comment)
{
@@ -85,7 +85,7 @@ using System.Security;
// by using the '*' as shown below:
[assembly: AssemblyVersion("4.0.8.0")]
#if !PocketPC
[assembly: AssemblyFileVersion("4.0.8.14618")]
[assembly: AssemblyFileVersion("4.0.8.14623")]
#endif
[assembly: CLSCompliant(true)]
@@ -35,11 +35,12 @@ namespace Newtonsoft.Json.Serialization
/// </summary>
public class ErrorContext
{
internal ErrorContext(object originalObject, object member, Exception error)
internal ErrorContext(object originalObject, object member, string path, Exception error)
{
OriginalObject = originalObject;
Member = member;
Error = error;
Path = path;
}
/// <summary>
@@ -58,6 +59,11 @@ namespace Newtonsoft.Json.Serialization
/// <value>The member that caused the error.</value>
public object Member { get; private set; }
/// <summary>
/// Gets the path of the JSON location when the error occurred.
/// </summary>
/// <value>The path of the JSON location when the error occurred.</value>
public string Path { get; private set; }
/// <summary>
/// Gets or sets a value indicating whether this <see cref="ErrorContext"/> is handled.
/// </summary>
/// <value><c>true</c> if handled; otherwise, <c>false</c>.</value>
@@ -37,7 +37,12 @@ namespace Newtonsoft.Json.Serialization
/// </summary>
public class JsonArrayContract : JsonContract
{
internal Type CollectionItemType { get; private set; }
/// <summary>
/// Gets the <see cref="Type"/> of the collection items.
/// </summary>
/// <value>The <see cref="Type"/> of the collection items.</value>
public Type CollectionItemType { get; private set; }
internal JsonContract CollectionItemContract { get; set; }
private readonly bool _isCollectionItemTypeNullableType;
@@ -42,8 +42,16 @@ namespace Newtonsoft.Json.Serialization
/// <value>The property name resolver.</value>
public Func<string, string> PropertyNameResolver { get; set; }
internal Type DictionaryKeyType { get; private set; }
internal Type DictionaryValueType { get; private set; }
/// <summary>
/// Gets the <see cref="Type"/> of the dictionary keys.
/// </summary>
/// <value>The <see cref="Type"/> of the dictionary keys.</value>
public Type DictionaryKeyType { get; private set; }
/// <summary>
/// Gets the <see cref="Type"/> of the dictionary values.
/// </summary>
/// <value>The <see cref="Type"/> of the dictionary values.</value>
public Type DictionaryValueType { get; private set; }
internal JsonContract DictionaryKeyContract { get; set; }
internal JsonContract DictionaryValueContract { get; set; }
@@ -79,10 +79,10 @@ namespace Newtonsoft.Json.Serialization
}
}
protected ErrorContext GetErrorContext(object currentObject, object member, Exception error)
protected ErrorContext GetErrorContext(object currentObject, object member, string path, Exception error)
{
if (_currentErrorContext == null)
_currentErrorContext = new ErrorContext(currentObject, member, error);
_currentErrorContext = new ErrorContext(currentObject, member, path, error);
if (_currentErrorContext.Error != error)
throw new InvalidOperationException("Current error context error is different to requested error.");
@@ -98,9 +98,9 @@ namespace Newtonsoft.Json.Serialization
_currentErrorContext = null;
}
protected bool IsErrorHandled(object currentObject, JsonContract contract, object keyValue, Exception ex)
protected bool IsErrorHandled(object currentObject, JsonContract contract, object keyValue, string path, Exception ex)
{
ErrorContext errorContext = GetErrorContext(currentObject, keyValue, ex);
ErrorContext errorContext = GetErrorContext(currentObject, keyValue, path, ex);
contract.InvokeOnError(currentObject, Serializer.Context, errorContext);
if (!errorContext.Handled)
@@ -712,7 +712,7 @@ namespace Newtonsoft.Json.Serialization
}
catch (Exception ex)
{
if (IsErrorHandled(dictionary, contract, keyValue, ex))
if (IsErrorHandled(dictionary, contract, keyValue, reader.Path, ex))
HandleError(reader, initialDepth);
else
throw;
@@ -767,39 +767,47 @@ namespace Newtonsoft.Json.Serialization
contract.InvokeOnDeserializing(list, Serializer.Context);
int initialDepth = reader.Depth;
int index = 0;
JsonContract collectionItemContract = GetContractSafe(contract.CollectionItemType);
JsonConverter collectionItemConverter = GetConverter(collectionItemContract, null);
while (ReadForType(reader, collectionItemContract, collectionItemConverter != null, true))
while (true)
{
switch (reader.TokenType)
try
{
case JsonToken.EndArray:
contract.InvokeOnDeserialized(list, Serializer.Context);
return wrappedList.UnderlyingCollection;
case JsonToken.Comment:
break;
default:
try
if (ReadForType(reader, collectionItemContract, collectionItemConverter != null, true))
{
switch (reader.TokenType)
{
object value = CreateValueNonProperty(reader, contract.CollectionItemType, collectionItemContract, collectionItemConverter);
case JsonToken.EndArray:
contract.InvokeOnDeserialized(list, Serializer.Context);
wrappedList.Add(value);
}
catch (Exception ex)
{
if (IsErrorHandled(list, contract, wrappedList.Count, ex))
{
HandleError(reader, initialDepth);
}
else
{
throw;
}
return wrappedList.UnderlyingCollection;
case JsonToken.Comment:
break;
default:
object value = CreateValueNonProperty(reader, contract.CollectionItemType, collectionItemContract, collectionItemConverter);
wrappedList.Add(value);
break;
}
}
else
{
break;
}
}
catch (Exception ex)
{
if (IsErrorHandled(list, contract, index, reader.Path, ex))
HandleError(reader, initialDepth);
else
throw;
}
finally
{
index++;
}
}
@@ -911,7 +919,7 @@ namespace Newtonsoft.Json.Serialization
}
catch (Exception ex)
{
if (IsErrorHandled(newObject, contract, memberName, ex))
if (IsErrorHandled(newObject, contract, memberName, reader.Path, ex))
HandleError(reader, initialDepth);
else
throw;
@@ -1155,71 +1163,88 @@ namespace Newtonsoft.Json.Serialization
switch (reader.TokenType)
{
case JsonToken.PropertyName:
string memberName = reader.Value.ToString();
try
{
// attempt exact case match first
// then try match ignoring case
JsonProperty property = contract.Properties.GetClosestMatchProperty(memberName);
string memberName = reader.Value.ToString();
if (property == null)
try
{
if (Serializer.MissingMemberHandling == MissingMemberHandling.Error)
throw CreateSerializationException(reader, "Could not find member '{0}' on object of type '{1}'".FormatWith(CultureInfo.InvariantCulture, memberName, contract.UnderlyingType.Name));
// attempt exact case match first
// then try match ignoring case
JsonProperty property = contract.Properties.GetClosestMatchProperty(memberName);
reader.Skip();
continue;
if (property == null)
{
if (Serializer.MissingMemberHandling == MissingMemberHandling.Error)
throw CreateSerializationException(reader, "Could not find member '{0}' on object of type '{1}'".FormatWith(CultureInfo.InvariantCulture, memberName, contract.UnderlyingType.Name));
reader.Skip();
continue;
}
if (property.PropertyContract == null)
property.PropertyContract = GetContractSafe(property.PropertyType);
JsonConverter propertyConverter = GetConverter(property.PropertyContract, property.MemberConverter);
if (!ReadForType(reader, property.PropertyContract, propertyConverter != null, false))
throw CreateSerializationException(reader, "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, memberName));
SetPropertyPresence(reader, property, propertiesPresence);
SetPropertyValue(property, propertyConverter, reader, newObject);
}
catch (Exception ex)
{
if (IsErrorHandled(newObject, contract, memberName, reader.Path, ex))
HandleError(reader, initialDepth);
else
throw;
}
if (property.PropertyContract == null)
property.PropertyContract = GetContractSafe(property.PropertyType);
JsonConverter propertyConverter = GetConverter(property.PropertyContract, property.MemberConverter);
if (!ReadForType(reader, property.PropertyContract, propertyConverter != null, false))
throw CreateSerializationException(reader, "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, memberName));
SetPropertyPresence(reader, property, propertiesPresence);
SetPropertyValue(property, propertyConverter, reader, newObject);
}
catch (Exception ex)
{
if (IsErrorHandled(newObject, contract, memberName, ex))
HandleError(reader, initialDepth);
else
throw;
}
break;
case JsonToken.EndObject:
foreach (KeyValuePair<JsonProperty, PropertyPresence> propertyPresence in propertiesPresence)
{
JsonProperty property = propertyPresence.Key;
PropertyPresence presence = propertyPresence.Value;
switch (presence)
foreach (KeyValuePair<JsonProperty, PropertyPresence> propertyPresence in propertiesPresence)
{
case PropertyPresence.None:
if (property.Required == Required.AllowNull || property.Required == Required.Always)
throw CreateSerializationException(reader, "Required property '{0}' not found in JSON.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName));
JsonProperty property = propertyPresence.Key;
PropertyPresence presence = propertyPresence.Value;
if (property.PropertyContract == null)
property.PropertyContract = GetContractSafe(property.PropertyType);
if (presence == PropertyPresence.None || presence == PropertyPresence.Null)
{
try
{
switch (presence)
{
case PropertyPresence.None:
if (property.Required == Required.AllowNull || property.Required == Required.Always)
throw CreateSerializationException(reader, "Required property '{0}' not found in JSON.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName));
if (HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer.DefaultValueHandling), DefaultValueHandling.Populate)
&& property.Writable)
property.ValueProvider.SetValue(newObject, EnsureType(reader, property.DefaultValue, CultureInfo.InvariantCulture, property.PropertyContract, property.PropertyType));
break;
case PropertyPresence.Null:
if (property.Required == Required.Always)
throw CreateSerializationException(reader, "Required property '{0}' expects a value but got null.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName));
break;
if (property.PropertyContract == null)
property.PropertyContract = GetContractSafe(property.PropertyType);
if (HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer.DefaultValueHandling), DefaultValueHandling.Populate)
&& property.Writable)
property.ValueProvider.SetValue(newObject, EnsureType(reader, property.DefaultValue, CultureInfo.InvariantCulture, property.PropertyContract, property.PropertyType));
break;
case PropertyPresence.Null:
if (property.Required == Required.Always)
throw CreateSerializationException(reader, "Required property '{0}' expects a value but got null.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName));
break;
}
}
catch (Exception ex)
{
if (IsErrorHandled(newObject, contract, property.PropertyName, reader.Path, ex))
HandleError(reader, initialDepth);
else
throw;
}
}
}
}
contract.InvokeOnDeserialized(newObject, Serializer.Context);
return newObject;
contract.InvokeOnDeserialized(newObject, Serializer.Context);
return newObject;
}
case JsonToken.Comment:
// ignore
break;
@@ -330,7 +330,7 @@ namespace Newtonsoft.Json.Serialization
}
catch (Exception ex)
{
if (IsErrorHandled(value, contract, property.PropertyName, ex))
if (IsErrorHandled(value, contract, property.PropertyName, writer.ContainerPath, ex))
HandleError(writer, initialDepth);
else
throw;
@@ -439,7 +439,7 @@ namespace Newtonsoft.Json.Serialization
}
catch (Exception ex)
{
if (IsErrorHandled(values.UnderlyingCollection, contract, index, ex))
if (IsErrorHandled(values.UnderlyingCollection, contract, index, writer.ContainerPath, ex))
HandleError(writer, initialDepth);
else
throw;
@@ -614,7 +614,7 @@ namespace Newtonsoft.Json.Serialization
}
catch (Exception ex)
{
if (IsErrorHandled(values.UnderlyingDictionary, contract, propertyName, ex))
if (IsErrorHandled(values.UnderlyingDictionary, contract, propertyName, writer.ContainerPath, ex))
HandleError(writer, initialDepth);
else
throw;