程序地带

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年,一如既往,不要在小问题上重复犯错!


版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/seanyan/p/14184995.html

随机推荐

简述驱动桥的动力传递路线_汽车传动系概述教案.docx

汽车传动系概述教案教案1周课型分类教学课题理论课传动系概述(上)知识目标:上课年月日(第节)时间教学目标1、掌握传动系统的组成:2、了解传动系统的功用。能力目标:1、掌握传动系统的组成:2、了解传动系...

小米智能生活 阅读(638)

c#modbus tcp通讯助手开源_Modbus协议是什么?

如需获得更多信息,文末点击“了解更多”MODBUS/TCP是简单的、中立厂商的用于管理和控制自动化设备的MODBUS系列通讯协议的派生产品。显而易见,它覆盖了使用TCP/I...

weixin_39987985 阅读(692)

LeetCode计数质数求解(204)(Python和C++实现)

一、题目说明统计所有小于非负整数n的质数的数量。示例1:输入:n=10输出:4解释:小于10的质数一共有4个,它们是2,3,5,7。示例...

AndrewGSD 阅读(291)

简述驱动桥的动力传递路线_驱动桥

第十四周教案项目汽车传动系任务驱动桥课时安排6课时第1.2课时驱动桥的结构新授课第3.4课时驱动桥的拆装与检修新授课第5.6课时驱动桥的故障诊断新授课授课日期授课班级17级汽修(2)班教学目标知识目标...

楚雨馨 阅读(137)