如何在不添加属性的情况下自定义 Json.net 中嵌套 属性 的反序列化
How can I customize the deserialization of a nested property in Json.net without adding attributes
假设我有这些 classes:
public class Bar
{
public Foo MyFoo { get; set; }
}
public class Foo
{
public string[] Stuff { get; set; }
}
我有这个 JSON 结构:
{
"MyFoo":
{
"Stuff":"those,are,my,stuff"
}
}
我有一个代码路径,其中使用如下代码将 JObject
转换为 Bar
:
myJObject.ToObject(typeof(Bar))
现在我需要做的是为 ToObject
提供自定义序列化程序,将字符串 属性 Stuff
转换为字符串数组(使用 string.Split(...).ToArray()
)
我被要求不要在客户端上添加属性 class 'Bar' 所以在环顾四周后似乎 ContractResolver
是有序的,但问题是解析器只允许我处理根类型的直接属性,在我的示例中是 Bar
,我无法在嵌套的 属性.
上注册 JsonConverter
所以我的问题是,使用 Json.net 是否可以实现?
- 请注意,我不仅需要对
Bar
class 执行此操作,而且需要对无限数量的具有未知结构的 classes 执行此操作,因此我无法硬编码一个适用于一种类型的 class. 的解决方案
根据您的描述,我不明白您为什么需要 ContractResolver
。你知道你想要特别反序列化的属性总是 string[]
类型,所以只需制作一个处理该类型的转换器即可。也许是这样的:
public class CsvStringConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(string[]);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JToken token = JToken.Load(reader);
if (token.Type == JTokenType.Null)
return null;
if (token.Type == JTokenType.String)
return ((string)token).Split(',');
if (token.Type == JTokenType.Array)
return token.ToObject<string[]>(serializer);
throw new JsonException("Unexpected token type: " + token.Type);
}
public override bool CanWrite => false;
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
然后,要将它与您的 JObject
一起使用,请创建一个新的 JsonSerializer
实例,向其添加转换器,并将序列化器传递给 ToObject()
方法,如下所示:
var serializer = new JsonSerializer();
serializer.Converters.Add(new CsvStringConverter());
var bar = myJObject.ToObject<Bar>(serializer);
此处的工作演示:https://dotnetfiddle.net/qmeBoh
假设我有这些 classes:
public class Bar
{
public Foo MyFoo { get; set; }
}
public class Foo
{
public string[] Stuff { get; set; }
}
我有这个 JSON 结构:
{
"MyFoo":
{
"Stuff":"those,are,my,stuff"
}
}
我有一个代码路径,其中使用如下代码将 JObject
转换为 Bar
:
myJObject.ToObject(typeof(Bar))
现在我需要做的是为 ToObject
提供自定义序列化程序,将字符串 属性 Stuff
转换为字符串数组(使用 string.Split(...).ToArray()
)
我被要求不要在客户端上添加属性 class 'Bar' 所以在环顾四周后似乎 ContractResolver
是有序的,但问题是解析器只允许我处理根类型的直接属性,在我的示例中是 Bar
,我无法在嵌套的 属性.
JsonConverter
所以我的问题是,使用 Json.net 是否可以实现?
- 请注意,我不仅需要对
Bar
class 执行此操作,而且需要对无限数量的具有未知结构的 classes 执行此操作,因此我无法硬编码一个适用于一种类型的 class. 的解决方案
根据您的描述,我不明白您为什么需要 ContractResolver
。你知道你想要特别反序列化的属性总是 string[]
类型,所以只需制作一个处理该类型的转换器即可。也许是这样的:
public class CsvStringConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(string[]);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JToken token = JToken.Load(reader);
if (token.Type == JTokenType.Null)
return null;
if (token.Type == JTokenType.String)
return ((string)token).Split(',');
if (token.Type == JTokenType.Array)
return token.ToObject<string[]>(serializer);
throw new JsonException("Unexpected token type: " + token.Type);
}
public override bool CanWrite => false;
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
然后,要将它与您的 JObject
一起使用,请创建一个新的 JsonSerializer
实例,向其添加转换器,并将序列化器传递给 ToObject()
方法,如下所示:
var serializer = new JsonSerializer();
serializer.Converters.Add(new CsvStringConverter());
var bar = myJObject.ToObject<Bar>(serializer);
此处的工作演示:https://dotnetfiddle.net/qmeBoh