JsonConvert.DeserializeObject,索引超出了数组界限

3

这些内容最初来源于https://github.com/JamesNK/Newtonsoft.Json/issues/469

我在stackoverflow上没有找到任何相关内容,所以我在项目的GitHub页面上发布了问题。


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

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

我在线程池中同时运行这10个任务,并且大约有20%的时间所有的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非常庞大,包含多个复合对象。然而,我可以使用DeserializeObject保存json并正确反序列化它,因此我认为对象结构不是问题所在。

对List错误进行一些研究表明,这是在尝试同时修改List对象时发生的。

1个回答

3

来自James Newton-King:

每次反序列化对象时都会创建一个新的JsonSerializerInternalReader。 每次反序列化都在其自己的状态下进行。 高负载的服务器在反序列化传入的JSON时,将同时反序列化许多东西,而不会出现问题。

我猜你有多个反序列化程序在同一列表上工作。


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

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

在尝试同时向列表中添加对象时,JsonSerializerInternalReader.cs文件的第1261行抛出了异常。

在看到我们代码中的实现方式后,我将摆脱静态备份,因为它并没有给我们提供任何帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接