所有这些都是来自https://github.com/JamesNK/Newtonsoft.Json/issues/469的原始内容

在这里发布是因为我第一次看SO却什么都没看到,所以我发布在了该项目的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很大,并且包含多个复合对象。但是,我可以保存json并使用DeserializeObject对其进行反序列化,因此我认为对象结构不是问题。

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

最佳答案

从詹姆斯·牛顿·金:


  每次您创建一个新的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行上引发了异常。

在了解了如何在我们的代码中实现之后,我将摆脱静态支持,因为它仍然无法为我们提供任何东西。

09-11 15:08