https://www.cnblogs.com/yijiayi/p/10051284.html

相信大家在工作中会经常遇见对json进行序列化与反序列化吧,但通常的序列化与反序列化中的json结构与c#中的类模型结构是相对应的,我们是否可以在序列化一个对象时候,让我们json的数据结构能按照自己的意愿,而不必与该对象的数据结构一样呢?,比如说,一个对象,只有一个名为"ID"的int类型的属性,值为1,如果序列化该对象,则能得到json:{"ID":1},但我现在希望得到的json的"ID"值是bool类型:{"ID":true}。要满足能够进行自定义序列化与反序列化的要求,我们可以运用json.net中的转换器JsonConverter。

  先来个简单的例子,就上面那个,一个对象,只有一个名为"ID"的int类型的属性,值为1,序列化该对象,如果ID值为1,则能得到json:{"ID":true},如果ID值不为1,得到json{"ID":false}。

  定义类:

  1. public class Model
  2. {
  3. public int ID { get; set; }
  4. }

  NuGet添加引用Newtonsoft.Json,再定义一个转换器类MyConverter,这个类要继承Newtonsoft.Json命名空间下的一个抽象类JsonConverter,我们先来看下这个抽象类的成员,有两个属性与三个抽象方法:

  

在MyConverter中我们要实现这三个抽象方法CanConvert()、ReadJson()、WriteJson(),并用特性[JsonConverter(typeof(MyConverter))]标记在我们要自定义序列化的类Model上就行了,就像这样:

  

  1. [JsonConverter(typeof(MyConverter))]
  2. public class Model
  3. {
  4. public int ID { get; set; }
  5. }

  在序列化Model对象的时候,程序会走到MyConverter下已经实现的WriteJson()方法,同理,反序列化会走到ReadJson()方法,而CanConvert方法是用于判断是否需要自定义序列化或者反序列化的,它的参数objectType对应着特性JsonConverter所标记类的对应Type类型。

  下面是MyConverter类的代码实现:

  

  1. public class MyConverter : JsonConverter
  2. {
  3. //是否开启自定义反序列化,值为true时,反序列化时会走ReadJson方法,值为false时,不走ReadJson方法,而是默认的反序列化
  4. public override bool CanRead => false;
  5. //是否开启自定义序列化,值为true时,序列化时会走WriteJson方法,值为false时,不走WriteJson方法,而是默认的序列化
  6. public override bool CanWrite => true;
  7.  
  8. public override bool CanConvert(Type objectType)
  9. {
  10. return typeof(Model) == objectType;
  11. }
  12.  
  13. public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
  14. {
  15. throw new NotImplementedException();
  16. }
  17.  
  18. public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
  19. {
  20. //new一个JObject对象,JObject可以像操作对象来操作json
  21. var jobj = new JObject();
  22. //value参数实际上是你要序列化的Model对象,所以此处直接强转
  23. var model = value as Model;
  24. if (model.ID != 1)
  25. {
  26. //如果ID值为1,添加一个键位"ID",值为false
  27. jobj.Add("ID",false);
  28. }
  29. else
  30. {
  31. jobj.Add("ID", true);
  32. }
  33. //通过ToString()方法把JObject对象转换成json
  34. var jsonstr = jobj.ToString();
  35. //调用该方法,把json放进去,最终序列化Model对象的json就是jsonstr,由此,我们就能自定义的序列化对象了
  36. writer.WriteValue(jsonstr);
  37. }
  38. }

  之后我们在Main函数里进行测试:

  

  1. static void Main(string[] args)
  2. {
  3. var model = new Model();
  4. model.ID = 1;
  5. var json = JsonConvert.SerializeObject(model);//由于ID值为1,得到json为{"ID":ture}
  6.  
  7. Console.WriteLine(json);
  8. model.ID = 2;
  9. json = JsonConvert.SerializeObject(model);//由于ID值不为1,得到json为{"ID":false}
  10. Console.WriteLine(json);
  11. Console.ReadKey();
  12. }

  但是,还有一个问题,如果我们把json再反序列化为Model对象时会发生错误,因为json在反序列化为已经标记MyConverter的类Model时,MyConverter里面CanRead属性是false,反序列时是走默认反序列化,不走ReadJson()方法,json里ID属性是bool类型的,而Model里的ID属性是int类型。有三个方法可以解决:1、该模型只做序列化操作不做反序列化操作;2、新定义一个类,它的属性ID是bool类型;3、MyConverter中CanRead属性设为true,并实现ReadJson()方法。以下是第三种方法ReadJson()函数的实现:

  1. public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
  2. {
  3. var model = new Model();
  4. //获取JObject对象,该对象对应着我们要反序列化的json
  5. var jobj = serializer.Deserialize<JObject>(reader);
  6. //从JObject对象中获取键位ID的值
  7. var id = jobj.Value<bool>("ID");
  8. //根据id值判断,进行赋值操作
  9. if (id)
  10. {
  11. model.ID = 1;
  12. }
  13. else
  14. {
  15. model.ID = 0;
  16. }
  17. //最终返回的model对象就是json反序列化所得到的Model对象
  18. //主要,这里的model对象不一定非得是Model类型,ReadJson()方法与WriteJson()方法是一样的,可以自由操作反序列生成的对象或者序列化生成的json
  19. return model;
  20. }

  下面附上全部代码:

  

  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. var model = new Model();
  6. model.ID = 1;
  7. var json = JsonConvert.SerializeObject(model);//由于ID值为1,得到json为{"ID":ture}
  8. var newModel = JsonConvert.DeserializeObject<Model>(json);//序列化得到的newModel对象ID值为1
  9. }
  10.  
  11. [JsonConverter(typeof(MyConverter))]
  12. public class Model
  13. {
  14. public int ID { get; set; }
  15. }
  16.  
  17. public class MyConverter : JsonConverter
  18. {
  19. //是否开启自定义反序列化,值为true时,反序列化时会走ReadJson方法,值为false时,不走ReadJson方法,而是默认的反序列化
  20. public override bool CanRead => true;
  21. //是否开启自定义序列化,值为true时,序列化时会走WriteJson方法,值为false时,不走WriteJson方法,而是默认的序列化
  22. public override bool CanWrite => true;
  23.  
  24. public override bool CanConvert(Type objectType)
  25. {
  26. return typeof(Model) == objectType;
  27. }
  28.  
  29. public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
  30. {
  31. var model = new Model();
  32. //获取JObject对象,该对象对应着我们要反序列化的json
  33. var jobj = serializer.Deserialize<JObject>(reader);
  34. //从JObject对象中获取键位ID的值
  35. var id = jobj.Value<bool>("ID");
  36. //根据id值判断,进行赋值操作
  37. if (id)
  38. {
  39. model.ID = 1;
  40. }
  41. else
  42. {
  43. model.ID = 0;
  44. }
  45. //最终返回的model对象就是json反序列化所得到的Model对象
  46. //主要,这里的model对象不一定非得是Model类型,ReadJson方法与WriteJson方法是一样的,可以自由操作反序列生成的对象或者序列化生成的json
  47. return model;
  48. }
  49.  
  50. public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
  51. {
  52. //new一个JObject对象,JObject可以像操作对象来操作json
  53. var jobj = new JObject();
  54. //value参数实际上是你要序列化的Model对象,所以此处直接强转
  55. var model = value as Model;
  56. if (model.ID != 1)
  57. {
  58. //如果ID值为1,添加一个键位"ID",值为false
  59. jobj.Add("ID",false);
  60. }
  61. else
  62. {
  63. jobj.Add("ID", true);
  64. }
  65. //通过ToString()方法把JObject对象转换成json
  66. var jsonstr = jobj.ToString();
  67. //调用该方法,把json放进去,最终序列化Model对象的json就是jsonstr,由此,我们就能自定义的序列化对象了
  68. writer.WriteValue(jsonstr);
  69. }
  70. }
  71. }

c# 通过json.net中的JsonConverter进行自定义序列化与反序列化的更多相关文章

  1. JSON和XML格式与对象的序列化及反序列化的辅助类

    下面的代码主要是把对象序列化为JSON格式或XML格式等 using System; using System.Collections.Generic; using System.Globalizat ...

  2. Json.Net学习(1) 实现简单的序列化和反序列化

    Attributes 可以用来控制Json.Net如何序列化和反序列化.Net对象. >JsonObjectAttribute--标记在类上,用于控制该类如何被序列化为一个Json对象(JSON ...

  3. C#中使用JavaScriptSerializer类实现序列化与反序列化

    1.添加引用 JavaScriptSerializer类的使用需要引用System.Web.Extensions.dll文件,根据路径:C:\Program Files (x86)\Reference ...

  4. 【json】与【枚举】的序列化和反序列化

    参考:Jackson – Deserialization from json to Java enums 问题描述 java中使用枚举时,如果涉及到restful调用,不可避免会涉及到枚举的序列化和反 ...

  5. 解决如下json格式的字符串不能使用DataContractJsonSerializer序列化和反序列化 分类: JSON 2015-01-28 14:26 72人阅读 评论(0) 收藏

    可以解决如下json格式的字符串不能使用DataContractJsonSerializer反序列化 {     "ss": "sss",     " ...

  6. 在C#中,Json的序列化和反序列化的几种方式总结

    在这篇文章中,我们将会学到如何使用C#,来序列化对象成为Json格式的数据,以及如何反序列化Json数据到对象. 什么是JSON? JSON (JavaScript Object Notation) ...

  7. 在C#中,Json的序列化和反序列化的几种方式总结 转载

    转载自  https://www.cnblogs.com/caofangsheng/p/5687994.html    谢谢 在这篇文章中,我们将会学到如何使用C#,来序列化对象成为Json格式的数据 ...

  8. C#中,Json的序列化和反序列化的几种方式总结

    在这篇文章中,我们将会学到如何使用C#,来序列化对象成为Json格式的数据,以及如何反序列化Json数据到对象. 什么是JSON? JSON (JavaScript Object Notation) ...

  9. day5-python中的序列化与反序列化-json&pickle

    一.概述 玩过稍微大型一点的游戏的朋友都知道,很多游戏的存档功能使得我们可以方便地迅速进入上一次退出的状态(包括装备.等级.经验值等在内的一切运行时数据),那么在程序开发中也存在这样的需求:比较简单的 ...

随机推荐

  1. Ubuntu安装Java环境经历

    1.权限不够 sudo su gedit /etc/sudoers 添加 用户名 ALL=(ALL:ALL) ALL 2.配置java 放到 /usr/lib/jvm/下 sudo gedit /et ...

  2. Android开发之常用Intent.Action【转】

    1.从google搜索内容 Intent intent = new Intent(); intent.setAction(Intent.ACTION_WEB_SEARCH); intent.putEx ...

  3. Typora 基础的使用方法

    大标题:通过ctrl + 数字 1 2 3 ....方式,还可以通过加# 的方式 一级标题 二级标题 三级标题 最多可以有6个#号 序号标题: 有序缩进是1. + tab 回车之后自动生成下一个序号 ...

  4. SHELL脚本编程-字符串处理

    SHELL脚本编程-字符串处理 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.字符串切片 [root@node101.yinzhengjie.org.cn ~]# echo { ...

  5. Docker万字详解!

    一.简介   1.了解Docker的前生LXC LXC为Linux Container的简写.可以提供轻量级的虚拟化,以便隔离进程和资源,而且不需要提供指令解释机制以及全虚拟化的其他复杂性.相当于C+ ...

  6. QA流程

    一.测试人员的介入时间 1.当产品经理与业务人员制定需求的时候,测试人员不宜介入: 2.当下一期的需求原型出来以后,这个时候就进入了需求评审.需求分析阶段,此时,测试人员应该介入: 3.当开发人员在编 ...

  7. 微信小程序~页面跳转和路由

    一个小程序拥有多个页面,我们可以通过wx.navigateTo推入一个新的页面,如图3-6所示,在首页使用2次wx.navigateTo后,页面层级会有三层,我们把这样的一个页面层级称为页面栈.

  8. 【后缀表达式求解】No.3.栈-evaluate-reverse-polish-notation题解(Java版)

    牛客网的题目链接 题目描述 Evaluate the value of an arithmetic expression in Reverse Polish Notation. Valid opera ...

  9. web自动化测试-自动化测试模型介绍

    一.线性测试 什么是线性测试? 通过录制或编写对应用程序的操作步骤产生相应的线性脚本,每个测试脚本相对独立,不产生依赖和调用,单纯的来模拟用户完整的操作场景 缺点 1.开发成本高,测试用例之间存在重复 ...

  10. SQL SERVER错误:已超过了锁请求超时时段。

    问题:远程连接数据库,无法打开视图,报错:SQL SERVER错误:已超过了锁请求超时时段. (Microsoft SQL Server,错误: 1222) 执行语句获取进程id select * f ...