JsonConvert.DeserializeObject,索引超出数组范围
JsonConvert.DeserializeObject, Index was outside the bounds of the array
本文全部来自https://github.com/JamesNK/Newtonsoft.Json/issues/469
发在这里是因为我第一次看SO,什么都没看到,所以我发在项目的GitHub页面上。
我们目前正在使用 JsonConvert.SerializeObject
和 JsonConvert.DeserializeObject<T>
在客户端和服务器之间发送数据。
我创建了一个工具来创建 10 个客户端,向 10 个不同的服务器发送命令,服务器序列化响应并通过网络发回,然后 10 个客户端反序列化本地机器上的对象。
我 运行 这 10 个任务并发在线程池中,大约 20% 的时间 all JsonConvert.DeserializeObject
调用失败并显示以下堆栈跟踪:
Error: Index was outside the bounds of the array.
at System.Collections.Generic.List1.Add(T item)
at System.Collections.Generic.List1.System.Collections.IList.Add(Object item)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateList(IList list, JsonReader reader, JsonArrayContract contract, JsonProperty containerProperty, String id)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateList(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue, String id)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, Object target)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, Object target)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings)
at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings)
at MyClientCode()
MyClientCode()
像这样使用 DeserializeObject
:
string json = GetServerResponse();
return JsonConvert.DeserializeObject<ResponseObject>(json);
ResponseObject
相当大,包括几个复合对象。但是,我可以保存 json 并使用 DeserializeObject
正确反序列化它,所以我认为对象结构不是问题。
对 List 错误进行一些研究表明,在尝试同时修改 List 对象时会发生这种情况。
来自 James Newton-King:
A new JsonSerializerInternalReader is created each time you
deserialize an object. Each deserialization happens in its own state.
A high volume server that it deserializing incoming JSON will be
deserializing many many things at the same time without issue.
My guess is you have multiple deserializers working over the same
list.
谢谢詹姆斯。深入挖掘后,我发现你是对的,我们对反序列化类型的多个实例使用了相同的列表对象。具体来说,该对象看起来像这样:
class Obj {
static List<string> _validSelections = new List<string>() { "One", "Two", "Three", "Four" };
public IEnumerable<string> ValidSelections { get { return _validSelections; } }
... more ...
}
当试图同时向列表中添加对象时,JsonSerializerInternalReader.cs 的第 1261 行抛出异常。
在看到它是如何在我们的代码中实现后,我将摆脱静态支持,因为它无论如何都没有为我们提供任何东西。
本文全部来自https://github.com/JamesNK/Newtonsoft.Json/issues/469
发在这里是因为我第一次看SO,什么都没看到,所以我发在项目的GitHub页面上。
我们目前正在使用 JsonConvert.SerializeObject
和 JsonConvert.DeserializeObject<T>
在客户端和服务器之间发送数据。
我创建了一个工具来创建 10 个客户端,向 10 个不同的服务器发送命令,服务器序列化响应并通过网络发回,然后 10 个客户端反序列化本地机器上的对象。
我 运行 这 10 个任务并发在线程池中,大约 20% 的时间 all JsonConvert.DeserializeObject
调用失败并显示以下堆栈跟踪:
Error: Index was outside the bounds of the array.
at System.Collections.Generic.List1.Add(T item)
at System.Collections.Generic.List1.System.Collections.IList.Add(Object item)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateList(IList list, JsonReader reader, JsonArrayContract contract, JsonProperty containerProperty, String id)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateList(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue, String id)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, Object target)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, Object target)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings)
at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings)
at MyClientCode()
MyClientCode()
像这样使用 DeserializeObject
:
string json = GetServerResponse();
return JsonConvert.DeserializeObject<ResponseObject>(json);
ResponseObject
相当大,包括几个复合对象。但是,我可以保存 json 并使用 DeserializeObject
正确反序列化它,所以我认为对象结构不是问题。
对 List 错误进行一些研究表明,在尝试同时修改 List 对象时会发生这种情况。
来自 James Newton-King:
A new JsonSerializerInternalReader is created each time you deserialize an object. Each deserialization happens in its own state. A high volume server that it deserializing incoming JSON will be deserializing many many things at the same time without issue.
My guess is you have multiple deserializers working over the same list.
谢谢詹姆斯。深入挖掘后,我发现你是对的,我们对反序列化类型的多个实例使用了相同的列表对象。具体来说,该对象看起来像这样:
class Obj {
static List<string> _validSelections = new List<string>() { "One", "Two", "Three", "Four" };
public IEnumerable<string> ValidSelections { get { return _validSelections; } }
... more ...
}
当试图同时向列表中添加对象时,JsonSerializerInternalReader.cs 的第 1261 行抛出异常。
在看到它是如何在我们的代码中实现后,我将摆脱静态支持,因为它无论如何都没有为我们提供任何东西。