怎么使用Newtonsoft.Json 处理存在继承关系的对象们

面向对象编程思想中,继承 确实是个好东西:提炼共性、逻辑复用、里氏转换。多少设计模式灵感都是以此为基点迸发,可见 继承 是多么重要,又是多么常见。
故而笔者觉得有必要带大家过一下 Json 在是怎么处理存在继承关系的 “对象们” 的。

写在前面:

一组继承了基类的差异化对象群体,可以声明基类类型的集合来统筹管理他们,这个就是里氏转换带来的便利。
Json 序列化和反序列化中如何原滋原味的保留这种 父亲可以代言儿子 的特性呢?
可以预见,使用public IList Businesses来装载下图的HotelHostel对象,
如果处理不好,反序列化后 Hostel 肯定会弄丢他的特殊服务!哦不~是弄丢了SpecialService字段的数据。

怎么使用Newtonsoft.Json 处理存在继承关系的对象们_第1张图片

实现:

其实呢,Newtonsoft.Json 真的是为亲们的操碎了心,早早的就准备好了案例,笔者Keyin的这些个代码便是直接Ctrl+C、Ctrl+V过来的,真懒!

namespace zFrame.Demo
{
    using Newtonsoft.Json;
    using System.Collections.Generic;
    using System.IO;
    using UnityEngine;

    public abstract class Business
    {
        public string Name { get; set; }
    }
    public class Hotel : Business
    {
        public int Stars { get; set; }
    }
    public class Hostel : Business
    {
        /// 特殊服务
        public string SpecialService { get; set; }
        public int Stars { get; set; }
    }

    public class Stockholder
    {
        public string FullName { get; set; }
        public IList Businesses { get; set; }
    }

    public class JsonSerializationDemo : MonoBehaviour
    {
        string path;
        Stockholder stockholder;
        private void Start()
        {
            path = FolderMaker.Creat(this, "json");
            Stockholder stockholder = new Stockholder
            {
                FullName = "Steve Stockholder",
                Businesses = new List
                {
                    new Hotel
                     {
                           Name = "Hudson Hotel",
                           Stars = 4
                     },
                    new Hostel
                    {
                        SpecialService="电击疗法",
                        Name="特殊人类研究所",
                        Stars=1
                    }
                 }
            };

            string jsonTypeNameAll = JsonConvert.SerializeObject(stockholder, Formatting.Indented, new JsonSerializerSettings
            {
                TypeNameHandling = TypeNameHandling.All
            });

            Debug.Log(jsonTypeNameAll);

            using (StreamWriter writer=File.CreateText(path+"/Data.json") )
            {
                writer.WriteLine(jsonTypeNameAll);
            }

        }

        private void Update()
        {
            if (Input.GetKeyDown(KeyCode.T))
            {
                string json = File.ReadAllText(path + "/Data.json");
                Debug.Log(json);
                stockholder = JsonConvert.DeserializeObject(json, new JsonSerializerSettings()
                {
                    TypeNameHandling = TypeNameHandling.Auto
                });

            }
        }
    }
}
  1. 为确保反系列化时类型正确,在序列化的时候必须使用创建一个序列化配置器,如下:


  2. 为了确保反序列化成功,在执行反序列化的时也需要创建配置器,如下:


    不可或缺哦
  3. 上面的代码中有一个奇奇怪怪的类:FolderMaker ,笔者用它获取Demo脚本的同级目录,方便保存序列化的数据, 往后不管Demo怎么被移植,这个反序列的数据永远在同级目录下呢。

动画演示:

demo

Tips:

  • 运行后脚本同级生成名称为 “Json” 的文件夹,刷新可见保存了的反序列化文件。
  • 打开反序列化文件,可见 Json 数据都是包含了类型了的, 用 $type 键映射。
  • 笔者修改了 Json 数据,按 T 反序列化,断点调试可见数据都正确的被抓取过来了。

扩展阅读:

TypeNameHandling setting
Unity3d 使用代码在脚本同级目录下创建文件夹 - FolderMaker

你可能感兴趣的:(怎么使用Newtonsoft.Json 处理存在继承关系的对象们)