自定义反序列化器仅适用于json.NET的某些字段

我正在尝试反序列化一些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 } ] } 

我想找到一种方法来定义仅针对某些字段的自定义反序列化。

在下面的代码中,我将需要注意的字段(自定义处理)和可以以某种方式自动完成的字段分开。

是否可以自动反序列化“正常”字段? (不需要任何特定的自定义处理)

 [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 { 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(); // I created the JsonConverter for those 2 properties configuration.c = myCustomProcessMethod(jsonObject["c"]); configuration.obj2 = myCustomProcessMethod2(jsonObject["obj2"].ToObject()); return configuration; } public override bool CanConvert(Type objectType) { return typeof(Configuration).IsAssignableFrom(objectType); } } 

既然你用Json.NET属性注释你的类型,一个更简单的解决方案似乎是使用[JsonConverter(Type)][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 { get; set; } } 

但是,如果您需要在Configuration上保留转换器(或者实际上是将转换器添加到JsonSerializerSettings.Converters并且无法将Json.NET属性添加到您的类型中),则可以使用JsonSerializer.Populate()来填充标准属性,当你第一次从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()); // 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; } } 

一种可能的方法是创建一个代理属性来正确序列化和反序列化。 通过使用ScriptIgnoreAttribute (也可能是JsonIgnoreAttribute ),不会对属性进行序列化。 这是一个例子:

 [ScriptIgnore] public int RealProperty { get; set; } public string RealPropertyProxy { get { return SerializeRealProperty(RealProperty); } set { RealProperty = DeserializeRealProperty(value); } } 

结果是只有代理按照您定义的方式进行序列化(基于不动产的值)。 只需以特殊方式修改需要序列化的属性,您就不需要实现特殊的JsonConverter