diff --git a/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs index e97dea47..7b608449 100644 --- a/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs +++ b/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs @@ -72,5 +72,5 @@ using System.Security; // by using the '*' as shown below: [assembly: AssemblyVersion("4.5.0.0")] #if !PocketPC -[assembly: AssemblyFileVersion("4.5.8.15131")] +[assembly: AssemblyFileVersion("4.5.8.15201")] #endif diff --git a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs index 0d1ccb31..3770ca0c 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs @@ -6656,6 +6656,141 @@ Parameter name: value", Assert.AreEqual(@"{""Before"":""Before!"",""Coordinates"":[[[1,1,1],[1,1,2]],[[1,2,1],[1,2,2]],[[2,1,1],[2,1,2]],[[2,2,1],[2,2,2]]],""After"":""After!""}", json); } + [Test] + public void SerializeArray3DWithConverter() + { + Array3DWithConverter aa = new Array3DWithConverter(); + aa.Before = "Before!"; + aa.After = "After!"; + aa.Coordinates = new[, ,] { { { 1, 1, 1 }, { 1, 1, 2 } }, { { 1, 2, 1 }, { 1, 2, 2 } }, { { 2, 1, 1 }, { 2, 1, 2 } }, { { 2, 2, 1 }, { 2, 2, 2 } } }; + + string json = JsonConvert.SerializeObject(aa, Formatting.Indented); + + Assert.AreEqual(@"{ + ""Before"": ""Before!"", + ""Coordinates"": [ + [ + [ + 1.0, + 1.0, + 1.0 + ], + [ + 1.0, + 1.0, + 2.0 + ] + ], + [ + [ + 1.0, + 2.0, + 1.0 + ], + [ + 1.0, + 2.0, + 2.0 + ] + ], + [ + [ + 2.0, + 1.0, + 1.0 + ], + [ + 2.0, + 1.0, + 2.0 + ] + ], + [ + [ + 2.0, + 2.0, + 1.0 + ], + [ + 2.0, + 2.0, + 2.0 + ] + ] + ], + ""After"": ""After!"" +}", json); + } + + [Test] + public void DeserializeArray3DWithConverter() + { + string json = @"{ + ""Before"": ""Before!"", + ""Coordinates"": [ + [ + [ + 1.0, + 1.0, + 1.0 + ], + [ + 1.0, + 1.0, + 2.0 + ] + ], + [ + [ + 1.0, + 2.0, + 1.0 + ], + [ + 1.0, + 2.0, + 2.0 + ] + ], + [ + [ + 2.0, + 1.0, + 1.0 + ], + [ + 2.0, + 1.0, + 2.0 + ] + ], + [ + [ + 2.0, + 2.0, + 1.0 + ], + [ + 2.0, + 2.0, + 2.0 + ] + ] + ], + ""After"": ""After!"" +}"; + + Array3DWithConverter aa = JsonConvert.DeserializeObject(json); + + Assert.AreEqual("Before!", aa.Before); + Assert.AreEqual("After!", aa.After); + Assert.AreEqual(4, aa.Coordinates.GetLength(0)); + Assert.AreEqual(2, aa.Coordinates.GetLength(1)); + Assert.AreEqual(3, aa.Coordinates.GetLength(2)); + Assert.AreEqual(1, aa.Coordinates[0, 0, 0]); + Assert.AreEqual(2, aa.Coordinates[1, 1, 1]); + } + [Test] public void DeserializeArray2D() { @@ -6776,6 +6911,26 @@ Parameter name: value", Assert.AreEqual(json, after); } + [Test] + public void DeserializeIncomplete3DArray() + { + string json = @"{""Before"":""Before!"",""Coordinates"":[/*hi*/[/*hi*/[1/*hi*/,/*hi*/1/*hi*/,1]/*hi*/,/*hi*/[1,1"; + + ExceptionAssert.Throws( + "Unexpected end when deserializing array. Path 'Coordinates[0][1][1]', line 1, position 90.", + () => JsonConvert.DeserializeObject(json)); + } + + [Test] + public void DeserializeIncompleteNotTopLevel3DArray() + { + string json = @"{""Before"":""Before!"",""Coordinates"":[/*hi*/[/*hi*/"; + + ExceptionAssert.Throws( + "Unexpected end when deserializing array. Path 'Coordinates[0]', line 1, position 48.", + () => JsonConvert.DeserializeObject(json)); + } + [Test] public void DeserializeNull3DArray() { @@ -6809,6 +6964,161 @@ Parameter name: value", Assert.AreEqual(json, after); } + + [Test] + public void SerializeReferenceTracked3DArray() + { + Event e1 = new Event + { + EventName = "EventName!" + }; + Event[,] array1 = new [,] { { e1, e1 }, { e1, e1 } }; + IList values1 = new List + { + array1, + array1 + }; + + string json = JsonConvert.SerializeObject(values1, new JsonSerializerSettings + { + PreserveReferencesHandling = PreserveReferencesHandling.All, + Formatting = Formatting.Indented + }); + + Assert.AreEqual(@"{ + ""$id"": ""1"", + ""$values"": [ + { + ""$id"": ""2"", + ""$values"": [ + [ + { + ""$id"": ""3"", + ""EventName"": ""EventName!"", + ""Venue"": null, + ""Performances"": null + }, + { + ""$ref"": ""3"" + } + ], + [ + { + ""$ref"": ""3"" + }, + { + ""$ref"": ""3"" + } + ] + ] + }, + { + ""$ref"": ""2"" + } + ] +}", json); + } + + [Test] + public void SerializeTypeName3DArray() + { + Event e1 = new Event + { + EventName = "EventName!" + }; + Event[,] array1 = new[,] { { e1, e1 }, { e1, e1 } }; + IList values1 = new List + { + array1, + array1 + }; + + string json = JsonConvert.SerializeObject(values1, new JsonSerializerSettings + { + TypeNameHandling = TypeNameHandling.All, + Formatting = Formatting.Indented + }); + + Assert.AreEqual(@"{ + ""$type"": ""System.Collections.Generic.List`1[[Newtonsoft.Json.Tests.Serialization.Event[,], Newtonsoft.Json.Tests]], mscorlib"", + ""$values"": [ + { + ""$type"": ""Newtonsoft.Json.Tests.Serialization.Event[,], Newtonsoft.Json.Tests"", + ""$values"": [ + [ + { + ""$type"": ""Newtonsoft.Json.Tests.Serialization.Event, Newtonsoft.Json.Tests"", + ""EventName"": ""EventName!"", + ""Venue"": null, + ""Performances"": null + }, + { + ""$type"": ""Newtonsoft.Json.Tests.Serialization.Event, Newtonsoft.Json.Tests"", + ""EventName"": ""EventName!"", + ""Venue"": null, + ""Performances"": null + } + ], + [ + { + ""$type"": ""Newtonsoft.Json.Tests.Serialization.Event, Newtonsoft.Json.Tests"", + ""EventName"": ""EventName!"", + ""Venue"": null, + ""Performances"": null + }, + { + ""$type"": ""Newtonsoft.Json.Tests.Serialization.Event, Newtonsoft.Json.Tests"", + ""EventName"": ""EventName!"", + ""Venue"": null, + ""Performances"": null + } + ] + ] + }, + { + ""$type"": ""Newtonsoft.Json.Tests.Serialization.Event[,], Newtonsoft.Json.Tests"", + ""$values"": [ + [ + { + ""$type"": ""Newtonsoft.Json.Tests.Serialization.Event, Newtonsoft.Json.Tests"", + ""EventName"": ""EventName!"", + ""Venue"": null, + ""Performances"": null + }, + { + ""$type"": ""Newtonsoft.Json.Tests.Serialization.Event, Newtonsoft.Json.Tests"", + ""EventName"": ""EventName!"", + ""Venue"": null, + ""Performances"": null + } + ], + [ + { + ""$type"": ""Newtonsoft.Json.Tests.Serialization.Event, Newtonsoft.Json.Tests"", + ""EventName"": ""EventName!"", + ""Venue"": null, + ""Performances"": null + }, + { + ""$type"": ""Newtonsoft.Json.Tests.Serialization.Event, Newtonsoft.Json.Tests"", + ""EventName"": ""EventName!"", + ""Venue"": null, + ""Performances"": null + } + ] + ] + } + ] +}", json); + + IList values2 = (IList)JsonConvert.DeserializeObject(json, new JsonSerializerSettings + { + TypeNameHandling = TypeNameHandling.All + }); + + Assert.AreEqual(2, values2.Count); + Assert.AreEqual("EventName!", values2[0][0, 0].EventName); + } } #if !(SILVERLIGHT || NETFX_CORE || PORTABLE) @@ -7133,4 +7443,30 @@ Parameter name: value", public int[,,] Coordinates { get; set; } public string After { get; set; } } + + public class Array3DWithConverter + { + public string Before { get; set; } + [JsonProperty(ItemConverterType = typeof(IntToFloatConverter))] + public int[, ,] Coordinates { get; set; } + public string After { get; set; } + } + + public class IntToFloatConverter : JsonConverter + { + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + writer.WriteValue(Convert.ToDouble(value)); + } + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + return Convert.ToInt32(reader.Value); + } + + public override bool CanConvert(Type objectType) + { + return objectType == typeof (int); + } + } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json.Tests/Serialization/SerializationErrorHandlingTests.cs b/Src/Newtonsoft.Json.Tests/Serialization/SerializationErrorHandlingTests.cs index 9e70659b..fbfdf416 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/SerializationErrorHandlingTests.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/SerializationErrorHandlingTests.cs @@ -97,6 +97,99 @@ namespace Newtonsoft.Json.Tests.Serialization Assert.AreEqual("Handle this!", c[2].ThrowError); } + [Test] + public void SerializingErrorIn3DArray() + { + ListErrorObject[,,] c = new ListErrorObject[,,] + { + { + { + new ListErrorObject + { + Member = "Value1", + ThrowError = "Handle this!", + Member2 = "Member1" + }, + new ListErrorObject + { + Member = "Value2", + Member2 = "Member2" + }, + new ListErrorObject + { + Member = "Value3", + ThrowError = "Handle that!", + Member2 = "Member3" + } + }, + { + new ListErrorObject + { + Member = "Value1", + ThrowError = "Handle this!", + Member2 = "Member1" + }, + new ListErrorObject + { + Member = "Value2", + Member2 = "Member2" + }, + new ListErrorObject + { + Member = "Value3", + ThrowError = "Handle that!", + Member2 = "Member3" + } + } + } + }; + + string json = JsonConvert.SerializeObject(c, new JsonSerializerSettings + { + Formatting = Formatting.Indented, + Error = (s, e) => + { + if (e.CurrentObject.GetType().IsArray) + e.ErrorContext.Handled = true; + } + }); + + Assert.AreEqual(@"[ + [ + [ + { + ""Member"": ""Value1"", + ""ThrowError"": ""Handle this!"", + ""Member2"": ""Member1"" + }, + { + ""Member"": ""Value2"" + }, + { + ""Member"": ""Value3"", + ""ThrowError"": ""Handle that!"", + ""Member2"": ""Member3"" + } + ], + [ + { + ""Member"": ""Value1"", + ""ThrowError"": ""Handle this!"", + ""Member2"": ""Member1"" + }, + { + ""Member"": ""Value2"" + }, + { + ""Member"": ""Value3"", + ""ThrowError"": ""Handle that!"", + ""Member2"": ""Member3"" + } + ] + ] +]", json); + } + [Test] public void SerializingErrorInChildObject() { @@ -339,6 +432,27 @@ namespace Newtonsoft.Json.Tests.Serialization Assert.AreEqual("[1] - 1 - Could not convert string to integer: b. Path '[1]', line 1, position 8.", errors[1]); } + [Test] + public void HandlingMultidimensionalArrayErrors() + { + string json = "[[\"a\",\"45\"],[\"b\",34]]"; + + List errors = new List(); + + 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] - 0 - Could not convert string to integer: a. Path '[0][0]', line 1, position 5.", errors[0]); + Assert.AreEqual("[1][0] - 0 - Could not convert string to integer: b. Path '[1][0]', line 1, position 16.", errors[1]); + } + [Test] public void ErrorHandlingAndAvoidingRecursiveDepthError() { diff --git a/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs index 7f6a12f6..c71e8475 100644 --- a/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs +++ b/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs @@ -91,7 +91,7 @@ using System.Security; // by using the '*' as shown below: [assembly: AssemblyVersion("4.5.0.0")] #if !PocketPC -[assembly: AssemblyFileVersion("4.5.8.15131")] +[assembly: AssemblyFileVersion("4.5.8.15201")] #endif [assembly: CLSCompliant(true)] diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs index b2be9b0c..c274cbfb 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs @@ -872,8 +872,6 @@ To fix this error either change the JSON to a {1} or change the deserialized typ contract.InvokeOnDeserializing(list, Serializer.Context); - int initialDepth = reader.Depth; - JsonContract collectionItemContract = GetContractSafe(contract.CollectionItemType); JsonConverter collectionItemConverter = GetConverter(collectionItemContract, null, contract, containerProperty); @@ -884,6 +882,8 @@ To fix this error either change the JSON to a {1} or change the deserialized typ while (true) { + int initialDepth = reader.Depth; + if (listStack.Count == rank) { try @@ -895,6 +895,7 @@ To fix this error either change the JSON to a {1} or change the deserialized typ case JsonToken.EndArray: listStack.Pop(); currentList = listStack.Peek(); + previousErrorIndex = null; break; case JsonToken.Comment: break; diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs index f940e81b..73d7a2f7 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs @@ -540,7 +540,7 @@ namespace Newtonsoft.Json.Serialization try { - JsonContract valueContract = contract.FinalItemContract ?? GetContractSafe(values); + JsonContract valueContract = contract.FinalItemContract ?? GetContractSafe(value); if (ShouldWriteReference(value, null, valueContract, contract, member)) { @@ -557,7 +557,7 @@ namespace Newtonsoft.Json.Serialization catch (Exception ex) { if (IsErrorHandled(values, contract, i, writer.ContainerPath, ex)) - HandleError(writer, initialDepth); + HandleError(writer, initialDepth + 1); else throw; }