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}。

  定义类:

        public class Model
{
public int ID { get; set; }
}

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

  

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

  

        [JsonConverter(typeof(MyConverter))]
public class Model
{
public int ID { get; set; }
}

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

  下面是MyConverter类的代码实现:

  

        public class MyConverter : JsonConverter
{
//是否开启自定义反序列化,值为true时,反序列化时会走ReadJson方法,值为false时,不走ReadJson方法,而是默认的反序列化
public override bool CanRead => false;
//是否开启自定义序列化,值为true时,序列化时会走WriteJson方法,值为false时,不走WriteJson方法,而是默认的序列化
public override bool CanWrite => true; public override bool CanConvert(Type objectType)
{
return typeof(Model) == objectType;
} public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
} public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
//new一个JObject对象,JObject可以像操作对象来操作json
var jobj = new JObject();
//value参数实际上是你要序列化的Model对象,所以此处直接强转
var model = value as Model;
if (model.ID != 1)
{
//如果ID值为1,添加一个键位"ID",值为false
jobj.Add("ID",false);
}
else
{
jobj.Add("ID", true);
}
//通过ToString()方法把JObject对象转换成json
var jsonstr = jobj.ToString();
//调用该方法,把json放进去,最终序列化Model对象的json就是jsonstr,由此,我们就能自定义的序列化对象了
writer.WriteValue(jsonstr);
}
}

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

  

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

  但是,还有一个问题,如果我们把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()函数的实现:

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

  下面附上全部代码:

  

    class Program
{
static void Main(string[] args)
{
var model = new Model();
model.ID = 1;
var json = JsonConvert.SerializeObject(model);//由于ID值为1,得到json为{"ID":ture}
var newModel = JsonConvert.DeserializeObject<Model>(json);//序列化得到的newModel对象ID值为1
} [JsonConverter(typeof(MyConverter))]
public class Model
{
public int ID { get; set; }
} public class MyConverter : JsonConverter
{
//是否开启自定义反序列化,值为true时,反序列化时会走ReadJson方法,值为false时,不走ReadJson方法,而是默认的反序列化
public override bool CanRead => true;
//是否开启自定义序列化,值为true时,序列化时会走WriteJson方法,值为false时,不走WriteJson方法,而是默认的序列化
public override bool CanWrite => true; public override bool CanConvert(Type objectType)
{
return typeof(Model) == objectType;
} public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var model = new Model();
//获取JObject对象,该对象对应着我们要反序列化的json
var jobj = serializer.Deserialize<JObject>(reader);
//从JObject对象中获取键位ID的值
var id = jobj.Value<bool>("ID");
//根据id值判断,进行赋值操作
if (id)
{
model.ID = 1;
}
else
{
model.ID = 0;
}
//最终返回的model对象就是json反序列化所得到的Model对象
//主要,这里的model对象不一定非得是Model类型,ReadJson方法与WriteJson方法是一样的,可以自由操作反序列生成的对象或者序列化生成的json
return model;
} public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
//new一个JObject对象,JObject可以像操作对象来操作json
var jobj = new JObject();
//value参数实际上是你要序列化的Model对象,所以此处直接强转
var model = value as Model;
if (model.ID != 1)
{
//如果ID值为1,添加一个键位"ID",值为false
jobj.Add("ID",false);
}
else
{
jobj.Add("ID", true);
}
//通过ToString()方法把JObject对象转换成json
var jsonstr = jobj.ToString();
//调用该方法,把json放进去,最终序列化Model对象的json就是jsonstr,由此,我们就能自定义的序列化对象了
writer.WriteValue(jsonstr);
}
}
}

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. 结队编程--java实现

    1.GitHub地址:https://github.com/caiyouling/Myapp 队友:钟小敏 GitHub地址:https://github.com/zhongxiao136/Myapp ...

  2. Linux_安装maven

    安装maven 1.首先要已经安装JDK 2.下载安装包,可以安装包下: 下载地址:https://mirrors.cnnic.cn/apache/maven/ wget https://mirror ...

  3. 肖哥HCNP-正式篇笔记

    21.网工学习环境准备. 一. 关掉所有杀毒软件及管家如阿健. 二. 安装环回网卡 (一定要先安装.) 1. 计算机设备管理 2. 在右侧最上端计算机名上方右键,点击过时硬件. 3. 下一步.手动选择 ...

  4. Springboot项目中Pom.xml报错

    摘要:使用idea,两次在maven上浪费时间,第一次不知道怎么就解决了,第二次记录一下解决办法 参考博客地址: https://blog.csdn.net/u013129944/article/de ...

  5. 网页代码编辑器Blocs for mac如何进行行的控制?

    行是Blocs应用程序中的关键结构元素之一,它们是列和Bloc容器,它们构成了构建站点布局的基础.在本篇文章中,我们介绍的是网页代码编辑器Blocs for mac如何进行行的控制? ] 网页代码编辑 ...

  6. ansible中的常用循环模块with_items

    ansible中的循环模块有很多,不过with_items最为常用,且较为简单,循环模块最多的功能就是将重复性的任务简单化,如下例子所示: - hosts: all remote_user: root ...

  7. 使用 ESlint、lint-staged 半自动提升项目代码质量

    最近在项目部署了ESlint还有一些配套的工具,比如 prettier husky lint-staged,有些心得写出来分享下. 依据本篇可以实现在git commit之时,重新格式化代码,同时进行 ...

  8. C++(四十五) — 类型转换(static_cast、dynamic_cast 、const_cast、reinterpreter_cast)

     0.总结 (1)要转换的变量,转换前.转换后.转换后的结果. (2)一般情况下,避免进行类型转换. 1._static_cast(静态类型转换,int 转换为char) 格式:TYPE B = st ...

  9. spring cloud (八) Config client 和项目公共配置

    1 pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns="h ...

  10. Koadic的安装和使用---http c2远控工具

    Koadic的安装和使用 2017.11.26 11:02 字数 690 阅读 611评论 0喜欢 2   概述 Koadic是DEFCON分型出来的一个后渗透工具,主要通过vbscript.jscr ...