-Fixed various multidimensional array bugs

This commit is contained in:
James Newton-King
2012-08-01 23:19:02 +12:00
parent 32dc957880
commit 4e4fdde9c4
6 changed files with 457 additions and 6 deletions
@@ -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
@@ -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<Array3DWithConverter>(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<JsonSerializationException>(
"Unexpected end when deserializing array. Path 'Coordinates[0][1][1]', line 1, position 90.",
() => JsonConvert.DeserializeObject<Array3D>(json));
}
[Test]
public void DeserializeIncompleteNotTopLevel3DArray()
{
string json = @"{""Before"":""Before!"",""Coordinates"":[/*hi*/[/*hi*/";
ExceptionAssert.Throws<JsonSerializationException>(
"Unexpected end when deserializing array. Path 'Coordinates[0]', line 1, position 48.",
() => JsonConvert.DeserializeObject<Array3D>(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<Event[,]> values1 = new List<Event[,]>
{
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<Event[,]> values1 = new List<Event[,]>
{
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<Event[,]> values2 = (IList<Event[,]>)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);
}
}
}
@@ -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<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] - 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()
{
@@ -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)]
@@ -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;
@@ -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;
}