使用 NewtonSoft 的 Json 库反序列化具有派生类型的字典
给定以下类结构(其中包括派生对象的字典),如何使用 NewtonSoft 的 Json 库进行序列化和反序列化?当我反序列化时,我遇到了异常。看起来重建字典时遇到了问题。
[JsonObject(MemberSerialization.OptIn)]
public class GameObject
{
[JsonProperty]
public string Id { get; set; }
[JsonProperty]
public string Name { get; set; }
[JsonProperty]
public ConcurrentDictionary<string, Component> Components;
public GameObject()
{
Components = new ConcurrentDictionary<string, Component>();
}
}
[JsonObject(MemberSerialization.OptIn)]
public class Component
{
[JsonIgnore] // Ignore circular reference
public GameObject GameObject { get; set; }
public Component()
{
}
}
[JsonObject(MemberSerialization.OptIn)]
public class TestComponent : Component
{
[JsonProperty]
public int MyProperty { get; set; }
public TestComponent()
{
}
}
var originalJson = JsonConvert.SerializeObject(srcObject, Formatting.None,
new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.All,
TypeNameAssemblyFormat = FormatterAssemblyStyle.Simple
});
var newObject = JsonConvert.DeserializeObject<GameObject>(originalJson,
new JsonSerializerSettings()
{
TypeNameHandling = TypeNameHandling.All,
TypeNameAssemblyFormat = FormatterAssemblyStyle.Simple
});
DeserializeObject 调用出现异常:
System.Reflection.TargetInvocationException was unhandled by user code
Message=Exception has been thrown by the target of an invocation.
Source=mscorlib
StackTrace:
at System.RuntimeMethodHandle._InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeType typeOwner)
at System.RuntimeMethodHandle.InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeType typeOwner)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
at Newtonsoft.Json.Serialization.JsonContract.InvokeOnDeserialized(Object o, StreamingContext context) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonContract.cs:line 135
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateDictionary(IWrappedDictionary dictionary, JsonReader reader, JsonDictionaryContract contract, String id) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 638
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateAndPopulateDictionary(JsonReader reader, JsonDictionaryContract contract, String id) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 593
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 387
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 223
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueProperty(JsonReader reader, JsonProperty property, Object target, Boolean gottenCurrentValue, Object currentValue) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 198
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObjectFromNonDefaultConstructor(JsonReader reader, JsonObjectContract contract, String id) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 876
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateAndPopulateObject(JsonReader reader, JsonObjectContract contract, String id) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 846
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 396
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 223
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueNonProperty(JsonReader reader, Type objectType, JsonContract contract) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 208
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 120
at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\JsonSerializer.cs:line 421
at Newtonsoft.Json.JsonSerializer.Deserialize(JsonReader reader, Type objectType) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\JsonSerializer.cs:line 413
at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\JsonConvert.cs:line 721
at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\JsonConvert.cs:line 683
at MF.Tests.GameServer.ComponentSerializationTests.TestSerializationOfObjectWithComponent() in C: \ComponentSerializationTests.cs:line 119
InnerException: System.NullReferenceException
Message=Object reference not set to an instance of an object.
Source=mscorlib
StackTrace:
at System.Collections.Concurrent.ConcurrentDictionary`2.InitializeFromCollection(IEnumerable`1 collection)
at System.Collections.Concurrent.ConcurrentDictionary`2.OnDeserialized(StreamingContext context)
InnerException:
更新:
如果将 ConcurrentDictionary 更改为 List 或 Dictionary,则代码将按预期工作。
我做错了什么?
Given the following class structure, which includes a dictionary of derived objects, how can I serialize and deserialize using NewtonSoft’s Json library? When I deserialize, I am getting an exception. It looks like it is having issues reconstituting the dictionary.
[JsonObject(MemberSerialization.OptIn)]
public class GameObject
{
[JsonProperty]
public string Id { get; set; }
[JsonProperty]
public string Name { get; set; }
[JsonProperty]
public ConcurrentDictionary<string, Component> Components;
public GameObject()
{
Components = new ConcurrentDictionary<string, Component>();
}
}
[JsonObject(MemberSerialization.OptIn)]
public class Component
{
[JsonIgnore] // Ignore circular reference
public GameObject GameObject { get; set; }
public Component()
{
}
}
[JsonObject(MemberSerialization.OptIn)]
public class TestComponent : Component
{
[JsonProperty]
public int MyProperty { get; set; }
public TestComponent()
{
}
}
var originalJson = JsonConvert.SerializeObject(srcObject, Formatting.None,
new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.All,
TypeNameAssemblyFormat = FormatterAssemblyStyle.Simple
});
var newObject = JsonConvert.DeserializeObject<GameObject>(originalJson,
new JsonSerializerSettings()
{
TypeNameHandling = TypeNameHandling.All,
TypeNameAssemblyFormat = FormatterAssemblyStyle.Simple
});
Exception on the DeserializeObject call:
System.Reflection.TargetInvocationException was unhandled by user code
Message=Exception has been thrown by the target of an invocation.
Source=mscorlib
StackTrace:
at System.RuntimeMethodHandle._InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeType typeOwner)
at System.RuntimeMethodHandle.InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeType typeOwner)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
at Newtonsoft.Json.Serialization.JsonContract.InvokeOnDeserialized(Object o, StreamingContext context) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonContract.cs:line 135
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateDictionary(IWrappedDictionary dictionary, JsonReader reader, JsonDictionaryContract contract, String id) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 638
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateAndPopulateDictionary(JsonReader reader, JsonDictionaryContract contract, String id) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 593
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 387
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 223
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueProperty(JsonReader reader, JsonProperty property, Object target, Boolean gottenCurrentValue, Object currentValue) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 198
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObjectFromNonDefaultConstructor(JsonReader reader, JsonObjectContract contract, String id) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 876
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateAndPopulateObject(JsonReader reader, JsonObjectContract contract, String id) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 846
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 396
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 223
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueNonProperty(JsonReader reader, Type objectType, JsonContract contract) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 208
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 120
at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\JsonSerializer.cs:line 421
at Newtonsoft.Json.JsonSerializer.Deserialize(JsonReader reader, Type objectType) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\JsonSerializer.cs:line 413
at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\JsonConvert.cs:line 721
at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\JsonConvert.cs:line 683
at MF.Tests.GameServer.ComponentSerializationTests.TestSerializationOfObjectWithComponent() in C: \ComponentSerializationTests.cs:line 119
InnerException: System.NullReferenceException
Message=Object reference not set to an instance of an object.
Source=mscorlib
StackTrace:
at System.Collections.Concurrent.ConcurrentDictionary`2.InitializeFromCollection(IEnumerable`1 collection)
at System.Collections.Concurrent.ConcurrentDictionary`2.OnDeserialized(StreamingContext context)
InnerException:
Update:
If change the ConcurrentDictionary to a List or a Dictionary, the code works as expected.
What am I doing wrong?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论