JsonConvert.DeserializeObject,Index超出了数组的范围

时间:2015-01-22 17:40:35

标签: c# json.net

所有这些都来自https://github.com/JamesNK/Newtonsoft.Json/issues/469

发布在这里,因为我第一次看到SO并没有看到任何内容,所以我发布了该项目的GitHub页面。


我们目前正在使用JsonConvert.SerializeObjectJsonConvert.DeserializeObject<T>在客户端和服务器之间发送数据。

我创建了一个工具,可以创建10个客户端,向10个不同的服务器发送命令,服务器序列化响应并通过网络将其发回,然后10个客户端反序列化本地计算机上的对象。

我在线程池中同时运行这10个任务,并且JsonConvert.DeserializeObject调用的所有的大约20%的时间失败,并带有以下堆栈跟踪:

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对象时会发生这种情况。

1 个答案:

答案 0 :(得分:3)

James Newton-King:

  

每次创建一个新的JsonSerializerInternalReader   反序列化一个对象。每个反序列化都发生在自己的状态中。   它将对传入的JSON进行反序列化的高容量服务器   在没有问题的情况下同时反复许多很多事情。

     

我的猜测是你有多个反序列化器在同一个工作   列表。


谢谢詹姆斯。深入挖掘后我发现你是对的,我们对反序列化类型的多个实例使用相同的列表对象。具体来说,对象看起来像这样:

class Obj {
    static List<string> _validSelections = new List<string>() { "One", "Two", "Three", "Four" };
    public IEnumerable<string> ValidSelections { get { return _validSelections; } }
    ... more ...
}

当尝试同时向对象添加对象时,JsonSerializerInternalReader.cs的第1261行抛出异常。

在我们的代码中看到这是如何实现之后,我将摆脱静态支持,因为它无论如何都没有为我们提供任何东西。