自定义反序列化器仅适用于json.NET的某些字段 [英] Custom deserializer only for some fields with json.NET
问题描述
我正在尝试反序列化一些JSON:
I'm trying to deserialize some JSON:
{
"a":1,
"b":25,
"c":"1-7",
"obj1":{
"a1":10,
"b1":45,
"c1":60
},
"obj2":[
{
"a2":100,
"b2":15,
"c2":50
},
{
"e2":"1,2,5-7",
"f2":"1,3-5",
"a2":25
}
]
}
我想找到一种只为某些字段定义自定义反序列化的方法.
I want to find a way to define a custom de-serialization only for some fields.
在下面的代码中,我分离了需要注意的字段(自定义处理)和可以自动完成的字段.
In the following code, I separated the fields that need some attention (custom processing) and the ones that could be done automatically somehow.
是否可以自动反序列化普通"字段? (不需要任何特定的自定义处理)
Is it possible to automatically deserialize the "normal" fields? (that don't need any specific custom processing)
[JsonConverter(typeof(ConfigurationSerializer))]
public class Configuration
{
public int a { get; set; }
public int b { get; set; }
public Obj1 obj1 { get; set; }
public int[] c { get; set; }
public IList<Obj2> obj2 { get; set; }
}
public class ConfigurationSerializer : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject jsonObject = JObject.Load(reader);
Configuration configuration = new Configuration();
// I would like this part to be automatic as I just repeat the default
// In the real case, I have many fields here!
configuration.a = (int)jsonObject["a"];
configuration.b = (int)jsonObject["b"];
configuration.obj1 = jsonObject["obj1"].ToObject<Obj1>();
// I created the JsonConverter for those 2 properties
configuration.c = myCustomProcessMethod(jsonObject["c"]);
configuration.obj2 = myCustomProcessMethod2(jsonObject["obj2"].ToObject<ValletConfiguration>());
return configuration;
}
public override bool CanConvert(Type objectType)
{
return typeof(Configuration).IsAssignableFrom(objectType);
}
}
推荐答案
由于无论如何都使用Json.NET属性注释类型,因此一种更简单的解决方案似乎是使用 [JsonConverter(Type)]
或
Since you are annotating your type with Json.NET attributes anyway, a simpler solution would seem to be to put the converters on the relevant properties using [JsonConverter(Type)]
or [JsonProperty(ItemConverterType = Type)]
:
public class Configuration
{
public int a { get; set; }
public int b { get; set; }
public Obj1 obj1 { get; set; }
// Converts the entire list to a compressed string
[JsonConverter(typeof(IntListConverter))]
public int[] c { get; set; }
// Converts each Obj2 item individually
[JsonProperty(ItemConverterType = typeof(Obj2Converter))]
public IList<Obj2> obj2 { get; set; }
}
不过,如果您需要将转换器保留在Configuration
上(或实际上是将转换器添加到 JsonSerializerSettings.Converters
并且无法将Json.NET属性添加到您的类型),则可以使用
Nevertheless, if you need to retain the converter on Configuration
(or are actually adding the converter to JsonSerializerSettings.Converters
and cannot add Json.NET attributes to your type), you can use JsonSerializer.Populate()
to populate the standard properties, as long as you first remove the custom properties from the JObject
:
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
var jsonObject = JObject.Load(reader);
var configuration = (existingValue as Configuration ?? new Configuration());
// I created the JsonConverter for those 2 properties
configuration.c = myCustomProcessMethod(jsonObject["c"].RemoveFromLowestPossibleParent());
configuration.obj2 = myCustomProcessMethod2(jsonObject["obj2"].RemoveFromLowestPossibleParent().ToObject<ValletConfiguration>());
// Populate the remaining standard properties
using (var subReader = jsonObject.CreateReader())
{
serializer.Populate(subReader, configuration);
}
return configuration;
}
使用扩展方法:
public static class JsonExtensions
{
public static JToken RemoveFromLowestPossibleParent(this JToken node)
{
if (node == null)
return null;
var contained = node.AncestorsAndSelf().Where(t => t.Parent is JContainer && t.Parent.Type != JTokenType.Property).FirstOrDefault();
if (contained != null)
contained.Remove();
// Also detach the node from its immediate containing property -- Remove() does not do this even though it seems like it should
if (node.Parent is JProperty)
((JProperty)node.Parent).Value = null;
return node;
}
}
这篇关于自定义反序列化器仅适用于json.NET的某些字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!