使用Json.Net处理json序列化和反序列化接口或继承类
以前一直没有怎么关注过Newtonsoft的Json.Net这个第三方的.NET Json框架,主要是我以前在开发项目的时候大多数使用的都是.NET自带的Json序列化类JavaScriptSerializer,但是最近在项目中需要序列化和反序列化一个实现接口的类,而如果使用JavaScriptSerializer的话就会出现问题,我们来看看如下场景。
首先我们有一个接口IPeople和一个实现了该接口的类Man
interface IPeople
{
string Name { get; set; }
int Age { get; set; }
} class Man : IPeople
{
public string Name { get; set; } public int Age { get; set; }
}
我们使用JavaScriptSerializer直接序列化IPeople接口
IPeople poeple = new Man();
poeple.Age = ;
poeple.Name = "Scott"; JavaScriptSerializer jsSerializer = new JavaScriptSerializer();
string textJson = jsSerializer.Serialize(poeple);
poeple = jsSerializer.Deserialize<IPeople>(textJson);
会得到序列化后的json文本textJson如下
{"Name":"Scott","Age":25}
我们可以看到在序列化后的json中没有任何属性说明这段json到底是由什么类序列化而来的,紧接着在JavaScriptSerializer执行jsSerializer.Deserialize<IPeople>(textJson)做反序列化的时候就抛出了异常提示IPeople没有默认无参构造函数,也就是说JavaScriptSerializer不知道应该把textJson中的json反序列化为类Man。
而如果我们使用的是Json.NET的话,就可以完美的实现接口IPeople的序列化和反序列化,我们来看看怎么使用Json.NET的序列化和反序列化
IPeople poeple = new Man();
poeple.Age = ;
poeple.Name = "Scott"; JsonSerializerSettings jsonSerializerSettings = new JsonSerializerSettings();
jsonSerializerSettings.TypeNameHandling = TypeNameHandling.All;//这一行就是设置Json.NET能够序列化接口或继承类的关键,将TypeNameHandling设置为All后,Json.NET会在序列化后的json文本中附加一个属性说明json到底是从什么类序列化过来的,也可以设置TypeNameHandling为Auto,表示让Json.NET自动判断是否需要在序列化后的json中添加类型属性,如果序列化的对象类型和声明类型不一样的话Json.NET就会在json中添加类型属性,反之就不添加,但是我发现TypeNameHandling.Auto有时候不太好用。。。
string textJson = JsonConvert.SerializeObject(poeple, jsonSerializerSettings);//将JsonSerializerSettings作为参数传入序列化函数,这样序列化后的Json就附带类型属性
poeple = JsonConvert.DeserializeObject<IPeople>(textJson, jsonSerializerSettings);//将JsonSerializerSettings作为参数传入反序列化函数,这样Json.NET就会读取json文本中的类型属性,知道应该反序列化成什么类型
这里IPeople接口能被成功序列化和返序列化的关键就是jsonSerializerSettings.TypeNameHandling = TypeNameHandling.All这行代码,我们来看看Json.NET序列化后的json文本信息
{"$type":"Json.Man, Json","Name":"Scott","Age":25}
可以看到Json.NET在序列化后的json文本中添加了一个属性叫$type来说明json是从Json.Man类序列化而来的,那么后面再反序列化的时候Json.NET就成功地将上面的json文本反序列化成了类Man.
所以Json.NET在做json的序列化和反序列化的时候比JavaScriptSerializer更全面,当然在使用JavaScriptSerializer的时候自定义Converter也可以做到序列化接口和继承类,但是这要麻烦很多。这一点也会让我以后更多使用Json.NET来实现json的序列化和反序列化。
给出一个设置TypeNameHandling.Auto的例子说明,是老外写的,我觉得将TypeNameHandling.Auto解释得很清楚了。
Json.Net has a setting that intelligently adds type information - declare it like this:
new JsonSerializer { TypeNameHandling = TypeNameHandling.Auto };
This will determine whether type embedding is required and add it where necessary. Lets say I had the following classes:
public class Message
{
public object Body { get; set; }
} public class Person
{
public string Name { get; set; }
} public class Manager : Person
{ } public class Department
{
private List<Person> _employees = new List<Person>();
public List<Person> Employees { get { return _employees; } }
}
Notice the Message Body is of type object, and that Manager subclasses Person. If I serialize a Message with a Department Body that has a single Manager I get this:
{
"Body":
{
"$type":"Department, MyAssembly",
"Employees":[
{
"$type":"Manager, MyAssembly",
"Name":"Tim"
}]
}
}
Notice how it's added the $type property to describe the Department and Manager types. If I now add a Person to the Employees list and change the Message Body to be of type Department like this:
public class Message
{
public Department Body { get; set; }
}
then the Body type annotation is no longer needed and the new Person is not annotated - absence of annotation assumes the element instance is of the declared array type. The serialized format becomes:
{
"Body":
{
"Employees":[
{
"$type":"Manager, MyAssembly",
"Name":"Tim"
},
{
"Name":"James"
}]
}
}
This is an efficient approach - type annotation is only added where required. While this is .NET specific, the approach is simple enough to handle that deserializers/message types on other platforms should be fairly easily extended to handle this.
I'd be reticent about using this in a public API though, as it is non-standard. In that case you'd want to avoid polymorphism, and make versioning and type information very explicit properties in the message.
最后通过我写的一个例子来演示怎么自定义和使用Json.Net的转换器,这个例子还阐述了Json.Net在序列化和反序列化实现了接口IEnumerable的类时所遇到的问题,有兴趣的朋友可以下载。
使用Json.Net处理json序列化和反序列化接口或继承类的更多相关文章
- DynamicObject扩展--实现JSON和DynamicObject的序列化与反序列化
度娘许久,找不到我满意的答案,于是自己东凑西凑实现一个. DynamicObject扩展--实现JSON和DynamicObject的序列化与反序列化,亲测良好. 看代码 using System; ...
- json相关注解和序列化与反序列化
使用jackson进行序列化时,往往会遇到后台某个实体对象的属性为null,当序列化成json时对应的属性也为null,可以用以下的注解方式完成当属性为null时不参与序列化: @JsonSerial ...
- C++中的通用结构定义,及相应的序列化、反序列化接口
一个通用的C++结构定义如下: typedef struct tagCommonStruct { long len; void* buff; }CommonStruct_st; 此接口对应的普通序列化 ...
- XML序列化与反序列化接口对接实战,看这篇就够了
关键字:c# .NET XML 序列化 反序列化 本文为接口对接实践经验分享,不对具体的XML概念定义进行阐述:涉及工具类及处理方法已在生产环境使用多年,可放心使用.当然如果你发现问题,或有不同想法, ...
- JSON与对象的序列化与反序列化
一.利用JavaScriptSerializer 类 System.Web.Script.Serialization空间,位于System.Web.extensions.dll中. JavaScrip ...
- ASP.NET中JSON对时间进行序列化和反序列化
JSON格式不直接支持日期和时间.DateTime值显示为“/Date(0+0800)/”形式的JSON字符串,其中第一个数字是GMT时区中自1970年1月1 日午夜以来按正常时间(非夏令时)经过的毫 ...
- C++ 基于rapidjson对json字符串的进行序列化与反序列化
json字符串的解析以封装在我们开发过程中经常见到, 尤其在socket通信上面, 在一次项目中碰到json字符串的进行解析, 而公司有没有封装好的库, 于是就自己基于开源的库进行了一次封装, 接下是 ...
- 使用Newtonsoft.Json.dll(JSON.NET)动态解析JSON、.net 的json的序列化与反序列化(一)
在开发中,我非常喜欢动态语言和匿名对象带来的方便,JSON.NET具有动态序列化和反序列化任意JSON内容的能力,不必将它映射到具体的强类型对象,它可以处理不确定的类型(集合.字典.动态对象和匿名对象 ...
- Newtonsoft.Json 的序列化与反序列化
首先补充一点,Json.Net是支持序列化和反序列化DataTable,DataSet,Entity Framework和NHibernate的.我举例说明DataTable的序列化和反序列化.创建一 ...
随机推荐
- 如何去掉word的背影图片?
从网上下载下来的word资料总有背影图片,看的人很烦,网上有一些去除背景图片的方法,我找到一个不用去背景图片也行的方法:先选View,再选Draft,背景图片就正在最上面显示了,这时候你也可以选中图片 ...
- win10 + gtx1060 + cuda8.0 + caffe + vs2013
1. 安装cuda8.0 1)先去官网下载cuda8.0 https://developer.nvidia.com/cuda-toolkit 2)下载完之后进行安装,安装时间有点长,请耐心等待,默认 ...
- 淘宝杨志丰:OceanBase--淘宝结构化大数据解决之道
时至今日,“Big data”(大数据)时代的来临已经毋庸置疑,尤其是在电信.金融等行业,几乎已经到了“数据就是业务本身”的地步.这种趋势已经让很多相信数据之力量的企业做出改变.恰逢此时,为了让更多的 ...
- maven 无法安装plugin的问题
spring有一个入门例子,在docker里跑spring-boot程序 下载后按照教程执行mvn package docker:build.并不能成功.会报错. [ERROR] No plugin ...
- JAVA字符串的GZIP压缩解压缩
package com.gzip; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import ...
- 解决多线程调用sql存储过程问题
场景: 我们程序现在改成多线程了,我现在需要把临时表中的数据给插入到TABLE_M中,但这时候可能其他的线程也在插入,我就不能用之前我们的方案了(select max(oid) from Tuning ...
- javascript 函数参数之中的undefined(zz)
开始看到很多js函数里都带一个undefined的参数,很是疑惑,后来查了查,原来是这样.假如我们定义了一个函数function a(){ if(arg1===undefined) alert(&q ...
- unresolved external symbol __report_rangecheckfailure 解决思路
__report_rangecheckfailure 是用来检查堆栈缓存溢出的,如果编译的时候打开GS(project property-->Configuration properties- ...
- pgbouncer+pg(fdw)+pg(datanode)分表方案
pgbouncer+pg(fdw)+pg(datanode)分表方案 (环境RHEL6.5,PG9.4.5,pgbouncer1.5.4,libevent2.0.22) 方案架构图如下: pgboun ...
- spring 官方下载地址
SPRING官方网站改版后,建议都是通过Maven和Gradle下载,对不使用Maven和Gradle开发项目的,下载就非常麻烦. 下给出Spring Framework jar官方直接下载路径: h ...