• Newton.Json中JsonConverter的使用


    一、使用场景:

    有两个类都继承了同一个抽象类:

    /// <summary>
    /// 沙盒基类
    /// </summary>
    abstract class SandBoxGanmeBase
    {
        /// <summary>
        /// 名称
        /// </summary>
        public string Name { get; set; }
    
        /// <summary>
        /// 版本
        /// </summary>
        public string Version { get; set; }
    
        /// <summary>
        /// 可以驾驶
        /// </summary>
        public bool CanDrive { get { return true; } }
    }
    
    /// <summary>
    /// GTA
    /// </summary>
    class GTA5 : SandBoxGanmeBase
    {
        public bool HasHotCoffe { get; set; }
    }
    
    /// <summary>
    /// Cyberpunk2077
    /// </summary>
    class Cyberpunk2077 : SandBoxGanmeBase
    {
        public bool CanModifyDingDing { get { return true; } }
    }

    把信息保存入json:

    string sJsonFile = AppDomain.CurrentDomain.BaseDirectory + "games.json";
    
    IList<SandBoxGanmeBase> games = new List<SandBoxGanmeBase>();
    
    games.Add(new GTA5()
    {
        Name = "GTA5",
        Version = "1.53",
        HasHotCoffe = true
    });
    
    games.Add(new Cyberpunk2077()
    {
        Name = "Cyberpunk2077",
        Version = "1.06"
    });
    
    string sJson = JsonConvert.SerializeObject(games, Formatting.Indented);
    
    if (!File.Exists(sJsonFile))
        File.Create(sJsonFile).Close();
    
    using (TextWriter chsTw = new StreamWriter(sJsonFile))
    {
        chsTw.WriteLine(sJson);
    chsTw.Flush();
    }

    games.json 内容:

     一般的,使用如下代码读取 games.json:

     string sJsonFile = AppDomain.CurrentDomain.BaseDirectory + "games.json";
    
     string sJson = string.Empty;
     using (StreamReader sr = new StreamReader(sJsonFile))
         sJson = sr.ReadToEnd();
    
     IList<SandBoxGanmeBase> games = JsonConvert.DeserializeObject<IList<SandBoxGanmeBase>>(sJson);

    会 catch ex 报错:

    因为,抽象类在 Newton.Json 反序列化时,无法确定继承抽象类的实例,因此,我们必须要告诉 Newton.Json:你需要使用哪个类来进行反序列化,因此,JsonConverter 应运而生。

    二、自定义 JsonConverter

    class MyJsonConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return typeof(SandBoxGanmeBase).IsAssignableFrom(objectType);
        }
    
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            try
            {
                var jsonObject = JObject.Load(reader);
                object target = null;
                JToken gameName;
                if (jsonObject.TryGetValue("Name", out gameName))
                {
                    switch (gameName.ToString())
                    {
                        case "GTA5":
                            target = new GTA5();
                            break;
                        case "Cyberpunk2077":
                            target = new Cyberpunk2077();
                            break;
                    }
                }
                serializer.Populate(jsonObject.CreateReader(), target);
                return target;
            }
            catch (Exception ex)
            {
                throw new Exception("解析异常:" + ex.Message);
            }
        }
    
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
    
        }
    }

    修改读取 games.json 代码为:

    string sJsonFile = AppDomain.CurrentDomain.BaseDirectory + "games.json";
    
    string sJson = string.Empty;
    using (StreamReader sr = new StreamReader(sJsonFile))
        sJson = sr.ReadToEnd();
    
    IList<SandBoxGanmeBase> games = JsonConvert.DeserializeObject<IList<SandBoxGanmeBase>>(sJson, new MyJsonConverter());

    反序列化正常:

    三、拓展----用特性方式使用 JsonConverter

    1、反序列化

    SandBoxGanmeBase 增加特性,修改为:

    /// <summary>
    /// 沙盒基类
    /// </summary>
    [JsonConverter(typeof(MyJsonConverter))]
    abstract class SandBoxGanmeBase
    {
        ...
    }

    读取 games.json 方法还原为:

    ...
    
    IList<SandBoxGanmeBase> games = JsonConvert.DeserializeObject<IList<SandBoxGanmeBase>>(sJson);

    2、序列化

    仅为 SandBoxGanmeBase 增加了特性,再进行序列化时,序列化的 Json 字符串为空,修改 MyJsonConverter,增加 CanWrite 属性:

    class MyJsonConverter : JsonConverter
    {
        ...

    public
    override bool CanWrite { get { return false; } } ...

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { } }

    这样,在序列化对象时,就使用 Newton.Json 默认的 WriteJson 而不是使用 MyJsonConvert 中重写的 WriteJson。

    这应该是2020年最后一篇博客记录了,2021年,一如既往,不要在小问题上重复犯错!

  • 相关阅读:
    4.2Python数据处理篇之Matplotlib系列(二)---plt.scatter()散点图
    4.1Python数据处理篇之Matplotlib系列(一)---初识Matplotlib
    3.8Python数据处理篇之Numpy系列(八)---Numpy的梯度函数
    3.7Python数据处理篇之Numpy系列(七)---Numpy的统计函数
    3.6Python数据处理篇之Numpy系列(六)---Numpy随机函数
    3.5Python数据处理篇之Numpy系列(五)---numpy文件的存取
    3.4Python数据处理篇之Numpy系列(四)---ndarray 数组的运算
    3.3Python数据处理篇之Numpy系列(三)---数组的索引与切片
    3.2Python数据处理篇之Numpy系列(二)--- ndarray数组的创建与变换
    3.1Python数据处理篇之Numpy系列(一)---ndarray对象的属性与numpy的数据类型
  • 原文地址:https://www.cnblogs.com/seanyan/p/14184995.html
Copyright © 2020-2023  润新知