zoukankan      html  css  js  c++  java
  • Newtonsoft.Json 处理多态类型的反序列化

    Newtonsoft.Json的序列化和反序列化很成熟也很好用, 最近在处理多态类型的反序列化中遇到了问题, 反序列化后只能到基类,而得不到也不能转换到子类。从网上查询了一番后,需要写一个创建类型的Converter, 下面我们一步一步来:

    1. 首先说明类型的定义, 为了做这个实验,我定义了一个基类和两个子类, 然后我要序列化的对象包含了这个基类的集合。

    namespace LexSry
    {
        using Newtonsoft.Json;
        using System.Collections.Generic;
        class DemoData
        {
            [JsonProperty("demoId")]
            public int DemoId { get; set; }
    
            [JsonProperty("demos")]
            public List<DemoBase> Demos { get; set; }
        }
    
        public class DemoBase
        {
            [JsonProperty("id")]
            public int Id { get; set; }
            [JsonProperty("name")]
            public string Name { get; set; }
            [JsonProperty("type")]
            public string Type { get; set; }
        }
    
        public class DemoA : DemoBase
        {
            [JsonProperty("color")]
            public string Color { get; set; }
    
        }
    
        public class DemoB: DemoBase
        {
            [JsonProperty("size")]
            public double[] Size { get; set; }
        }
    }

    2. 序列化,反序列化方法。反序列化时使用 JsonConvert.DeserializeObject<T>(string value, param JsonConverter[] converter)。 通过自己定义JsonConverter来实现创建相应的子类。

    在本演示中, 我首先创建了抽象类 JsonCreationConverter<T>:JsonConverter ,

    其次, 针对于DemoBase的解析, 我创建了 JsonDemoConverter:JsonCreationConverter<DemoBase>

        class JsonParser3
        {
            public static void WriteJson(object t, string file)
            {
                JsonSerializer serializer = new JsonSerializer();
                using (StreamWriter sw = new StreamWriter(file))
                {
                    using (JsonWriter writer = new JsonTextWriter(sw))
                    {
                        serializer.Serialize(writer, t);
                    }
                }
            }
    
            public static void ReadJson<T>(string file, out T obj)
            {   
                JsonSerializer serializer = new JsonSerializer();
                using (StreamReader sr = new StreamReader(file))
                {
                    obj = JsonConvert.DeserializeObject<T>(sr.ReadToEnd(),new JsonDemoConverter());
                }
            }
        }
    
        public abstract class JsonCreationConverter<T>:JsonConverter
        {
            protected abstract T Create(Type objectType, JObject jsonObject);
            public override bool CanConvert(Type objectType)
            {
                return typeof(T).IsAssignableFrom(objectType);
            }
    
            public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
            {
                var jsonObject = JObject.Load(reader);
                var target = Create(objectType, jsonObject);
                serializer.Populate(jsonObject.CreateReader(), target);
                return target;
            }
    
            public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
            {
                throw new NotImplementedException();
            }
        }
    
        public class JsonDemoConverter:JsonCreationConverter<DemoBase>
        {
            protected override DemoBase Create(Type objectType, JObject jsonObject)
            {
                var typeName = jsonObject["type"].ToString();
                switch(typeName)
                {
                    case "A":
                        return new DemoA();
                    case "B":
                        return new DemoB();
                    default: return null;
                }
            }
        }
    }

    3. 在代码中实现将内存中的对象序列化到test.json中, 然后,从test.json中将数据反序列化到内存对象nData:

                DemoData data = new DemoData()
                {
                    DemoId = 1,
                    Demos = new List<DemoBase>()
                    {
                        new DemoA() {Id=1, Name="demoA", Type="A",Color="red" },
                        new DemoB() {Id=2, Name="", Type="B",Size= new double[]{ 10,10} }
                    }
                };
    
                JsonParser3.WriteJson(data, "test.json");
    
                DemoData nData = new DemoData();
                JsonParser3.ReadJson<DemoData>("test.json", out nData);

    4. test.json中的数据:

    {
      "demoId": 1,
      "demos": [
        {
          "color": "red",
          "id": 1,
          "name": "demoA",
          "type": "A"
        },
        {
          "size": [ 10.0, 10.0 ],
          "id": 2,
          "name": "",
          "type": "B"
        }
      ]
    }

    5. 反序列化后, 内存中得到的对象nData

  • 相关阅读:
    非常简洁的js图片轮播
    js广告图片轮播
    图片轮播
    分享到QQ空间、新浪微博、腾讯微博和人人网
    五星简单操作
    Struts2 多文件上传
    CSS3实践之路(六):CSS3的过渡效果(transition)与动画(animation)
    JavaScript中的数据类型
    JavaScript中对象是否需要加引号?
    变量提升(hoisting)
  • 原文地址:https://www.cnblogs.com/qixue/p/5292374.html
Copyright © 2011-2022 走看看