自定义反序列化程序仅适用于某些具有 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> 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)][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 属性),则可以使用 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<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;
    }
}

一种可能的方法是创建一个代理属性来正确序列化和反序列化。通过使用 ScriptIgnoreAttribute(也可能是 JsonIgnoreAttribute),真实属性不会被序列化。下面是一个示例:

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

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

相关内容

  • 没有找到相关文章

最新更新