C# 为什么JsonConvert.DeserializeObject不使用指定的JsonConverter?
我已经编写了一个自定义的C# 为什么JsonConvert.DeserializeObject不使用指定的JsonConverter?,c#,json,json.net,deserialization,C#,Json,Json.net,Deserialization,我已经编写了一个自定义的JsonConverter,我可以将它分配给JsonSerializerSettings,并与JsonConvert.DeserializeObject的通用覆盖一起使用,很好: var settings = new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All, Converters = new List<JsonConverter>() { new My
JsonConverter
,我可以将它分配给JsonSerializerSettings
,并与JsonConvert.DeserializeObject
的通用覆盖一起使用,很好:
var settings = new JsonSerializerSettings()
{
TypeNameHandling = TypeNameHandling.All,
Converters = new List<JsonConverter>() { new MyConverter() }
};
var x = JsonConvert.DeserializeObject<MyType>(input, settings);
输出:
Creating Example...
...Example Ctor: d860aa00-4493-4ab0-b681-f0af7b123212
Serializing e1...
e1: {"$type":"UnitTests.Serialization.Example, UnitTests","ExampleProp":"some value"}
Deserializing e2 - using DeserializeObject<Example>...
...ExampleConverter.ReadJson...
...Example Ctor: 00000000-0000-0000-0000-000000000000
e2: {"$type":"UnitTests.Serialization.Example, UnitTests","ExampleProp":"some value"}
Deserializing e3 - using DeserializeObject...
...Example Default Ctor...
e3: {"$type":"UnitTests.Serialization.Example, UnitTests","ExampleProp":"some value"}
正在创建示例。。。
…示例:d860aa00-4493-4ab0-b681-f0af7b123212
序列化e1。。。
e1:{“$type”:“UnitTests.Serialization.Example,UnitTests”,“ExampleProp”:“some value”}
反序列化e2-使用反序列化对象。。。
…ExampleConverter.ReadJson。。。
…示例:00000000-0000-0000-0000-000000000000
e2:{“$type”:“UnitTests.Serialization.Example,UnitTests”,“ExampleProp”:“some value”}
反序列化e3-使用反序列化对象。。。
…示例默认Ctor。。。
e3:{“$type”:“UnitTests.Serialization.Example,UnitTests”,“ExampleProp”:“some value”}
编辑:我也发现了这一点,但答案似乎是错误的:对于我的特定用例,以下结果是正确的:
public object DeserializeFromTypedString(string input, JsonSerializerSettings settings)
{
var r = new Regex(@"^\{\s*""\$type"":\s*""([^""]+)""");
var m = r.Match(input);
if (m.Success)
{
var t = Type.GetType(m.Groups[1].Value);
return Newtonsoft.Json.JsonConvert.DeserializeObject(input, t, settings);
}
else
{
throw new Exception("$type not found!");
}
}
其思想是手动解析$type
定义的字符串,解析类型并使用该类型调用相应的反序列化对象
重载
这对我来说已经足够好了,因为在我的特定用例中,我总是将JSON作为表示一个根对象(而不是数组)的字符串(而不是流或JToken)。该解决方案可以进行相应调整,但我仍然希望有更好/更清洁的解决方案
如果我在上面的例子中添加方法并交换相应的行
Console.WriteLine("\nDeserializing e3 - using DeserializeFromTypeString...");
var e3 = DeserializeFromTypedString(json, readSettings);
…输出是(正确的):
正在创建示例。。。
…示例:b5af2c3f-1c03-49d8-85c6-f3ff60c9f711
序列化e1。。。
e1:{“$type”:“UnitTests.Serialization.Example,UnitTests”,“Guid”:“b5af2c3f-1c03-49d8-85c6-f3ff60c9f711”,“ExampleProp”:“某些值”}
反序列化e2-使用反序列化对象。。。
…ExampleConverter.ReadJson。。。
…示例:00000000-0000-0000-0000-000000000000
e2:{“$type”:“UnitTests.Serialization.Example,UnitTests”,“Guid”:“00000000-0000-0000-0000-000000000000”,“ExampleProp”:“some value”}
反序列化e3-使用反序列化FromTypedString。。。
…ExampleConverter.ReadJson。。。
…示例:00000000-0000-0000-0000-000000000000
e3:{“$type”:“UnitTests.Serialization.Example,UnitTests”,“Guid”:“00000000-0000-0000-0000-000000000000”,“ExampleProp”:“some value”}
请注意,在这两种反序列化情况下,
ExampleConverter.ReadJson
和exampleCtor
的输出都表明我的自定义转换器确实在使用中。(我也在实际代码中使用嵌套对象成功地测试了它。)您能添加最少的类和示例json字符串来演示这个问题吗,特别是CanConvert
方法。基本问题是在反序列化过程中,调用CanConvert
时使用声明的类型而不是实际的类型,因为“$type”
属性尚未读取(因为它需要在ReadJson()
中处理)。看一看,并寻找解决办法。纳闷:为什么要投反对票?
Console.WriteLine("\nDeserializing e3 - using DeserializeFromTypeString...");
var e3 = DeserializeFromTypedString(json, readSettings);
Creating Example...
...Example Ctor: b5af2c3f-1c03-49d8-85c6-f3ff60c9f711
Serializing e1...
e1: {"$type":"UnitTests.Serialization.Example, UnitTests","Guid":"b5af2c3f-1c03-49d8-85c6-f3ff60c9f711","ExampleProp":"some value"}
Deserializing e2 - using DeserializeObject<Example>...
...ExampleConverter.ReadJson...
...Example Ctor: 00000000-0000-0000-0000-000000000000
e2: {"$type":"UnitTests.Serialization.Example, UnitTests","Guid":"00000000-0000-0000-0000-000000000000","ExampleProp":"some value"}
Deserializing e3 - using DeserializeFromTypedString...
...ExampleConverter.ReadJson...
...Example Ctor: 00000000-0000-0000-0000-000000000000
e3: {"$type":"UnitTests.Serialization.Example, UnitTests","Guid":"00000000-0000-0000-0000-000000000000","ExampleProp":"some value"}