Newton.Json中JsonConverter的使用

  • A+
所属分类:.NET技术
摘要

一、使用场景: 有两个类都继承了同一个抽象类: 把信息保存入json: games.json 内容:

一、使用场景:

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

/// <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 内容:

Newton.Json中JsonConverter的使用

 一般的,使用如下代码读取 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中JsonConverter的使用

因为,抽象类在 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());

反序列化正常:

Newton.Json中JsonConverter的使用

 

三、拓展----用特性方式使用 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年,一如既往,不要在小问题上重复犯错!