Json.Net系列教程 3.Json.Net序列化和反序列化设置
原文 Json.Net系列教程 3.Json.Net序列化和反序列化设置
首先补充一点,Json.Net是支持序列化和反序列化DataTable,DataSet,Entity Framework和NHibernate的.我举例说明DataTable的序列化和反序列化.
创建一个DataTable对象,如下:

DataTable dt = new DataTable();
DataColumn dcName = new DataColumn("Name");
DataColumn dcAge = new DataColumn("Age");
DataColumn dcCity = new DataColumn("City"); dt.Columns.Add(dcName);
dt.Columns.Add(dcAge);
dt.Columns.Add(dcCity);
for (int i = ; i < ; i++)
{
DataRow dr = dt.NewRow();
dr[] = "Name" + i;
dr[] = "Age" + i;
dr[] = "City" + i;
dt.Rows.Add(dr);
}

序列化:
string json = JsonConvert.SerializeObject(dt);
Console.WriteLine(json);
结果:

利用上面得到的序列化字符串反序列化:

DataTable dt1 = JsonConvert.DeserializeObject<DataTable>(json);
for (int i = ; i < dt1.Rows.Count; i++)
{
DataRow dr = dt1.Rows[i];
Console.WriteLine("{0}\t{1}\t{2}\t", dr[], dr[], dr[]);
}

结果:

预备知识:
要想实现对Json.Net序列化和反序列化的控制,就要用到类JsonSerializerSettings,用法很简单实例化一个对象,并把它赋值给JsonConvert的参数即可.
var jSetting = new JsonSerializerSettings();
string json = JsonConvert.SerializeObject(obj,jSetting);
开始之前,我还是先创建一员工类:

public class Staff
{
public string Name { get; set; }
public int Age { get; set; }
public string Gender { get; set; }
public string DepartmentName { get; set; }
public Staff Leader { get; set; }
}

这里的空值指的是引用类型为NULL时,Json.Net如何处理.通过设置jSetting.NullValueHandling的值来确定,该值为枚举类型.
NullValueHandling.Ignore |
忽略为NULL的值 |
NullValueHandling.Include |
默认值,包括为NULL的值 |
实例:

Staff jack = new Staff { Name = "Jack", Age = , Gender = "Male", DepartmentName = "Personnel Department", Leader = null };
var jSetting = new JsonSerializerSettings();
jSetting.NullValueHandling = NullValueHandling.Ignore;
string json = JsonConvert.SerializeObject(jack,jSetting);
Console.WriteLine(json);

结果:

一般是对于值类型的处理,通过设置jSetting.DefaultValueHandling的值来确定,该值为枚举类型.
DefaultValueHandling.Ignore |
序列化和反序列化时,忽略默认值 |
DefaultValueHandling.Include |
序列化和反序列化时,包含默认值 |
给成员设置默任值,用到"DefaultValue(value)"特性,当然别忘了引入命名空间"System.ComponentModel",假设员工的年龄默认值为30
[DefaultValue()]
public int Age { get; set; }
序列化时我想忽略为默认值的成员

Staff jack = new Staff { Name = "Jack", Age = , Gender = "Male", DepartmentName = "Personnel Department", Leader = null };
var jSetting = new JsonSerializerSettings();
jSetting.DefaultValueHandling = DefaultValueHandling.Ignore;
string json = JsonConvert.SerializeObject(jack,jSetting);
Console.WriteLine(json);

结果:

首先介绍Json.Net序列化的模式:OptOut 和 OptIn.
| OptOut | 默认值,类中所有公有成员会被序列化,如果不想被序列化,可以用特性JsonIgnore |
| OptIn | 默认情况下,所有的成员不会被序列化,类中的成员只有标有特性JsonProperty的才会被序列化,当类的成员很多,但客户端仅仅需要一部分数据时,很有用 |
假如客户仅仅需要员工的姓名,此时

[JsonObject(Newtonsoft.Json.MemberSerialization.OptIn)]
public class Staff
{
[JsonProperty]
public string Name { get; set; }
public int Age { get; set; }
public string Gender { get; set; }
public string DepartmentName { get; set; }
public Staff Leader { get; set; }
}

序列化:
Staff jack = new Staff { Name = "Jack", Age = , Gender = "Male", DepartmentName = "Personnel Department", Leader = null };
string json = JsonConvert.SerializeObject(jack);
结果:

如果客户不想要员工的领导信息

public class Staff
{
public string Name { get; set; }
public int Age { get; set; }
public string Gender { get; set; }
public string DepartmentName { get; set; }
[JsonIgnore]
public Staff Leader { get; set; }
}

序列化:
Staff tom = new Staff { Name = "Tome", Age = , Gender = "Male", DepartmentName = "Personnel Department"};
Staff jack = new Staff { Name = "Jack", Age = , Gender = "Male", DepartmentName = "Personnel Department", Leader = tom };
string json = JsonConvert.SerializeObject(jack);
Console.WriteLine(json);
结果:

Json.Net序列化对象时,默认情况下仅仅序列化公有成员,如果想要非公有成员也被序列化,就要在该成员上加特性"JsonProperty"
JsonConverters会在序列化和反序列化时被用到。JsonConverters允许手动对Json的控制。当Json的结构很复杂 和你想改变一个类型怎么样被序列化时,这是非常有用的。当一个JsonConverters被添加到JsonSerializer时,它会检查每一要被序 列化和反序列化的值,并返回CanConvert,如果为True,则JsonConverter读和写这个值;需要注意的是,虽然 JsonConverter能够使你可以完全的控制Json的值,但是很多的Json.Net序列化的特性被限制,像是类型名称和引用处理。所有的 JsonConvert都在命名空间 "Newtonsoft.Json.Converters"下
这是Json.Net中自带的两个处理日期的类,默认是IsoDateTimeConverter ,它的格式是"yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK".另一个是JavaScriptTimeConverter,它的格式是 "new Date(ticks)",其实返回的是一个JavaScript的Date对象.
有两种方式来应用JsonConverter,改变Json序列化和反序列化的行为.
假设我们为员工添加两个日期类型的成员,出生日期和入职日期

public class Staff
{
public string Name { get; set; }
public int Age { get; set; }
public string Gender { get; set; }
public string DepartmentName { get; set; }
public Staff Leader { get; set; }
public DateTime BirthDate { get; set; }
public DateTime EmploymentDate { get; set; }
}

我们的客户要求日期类型的成员返回javascript的日期对象
Staff jack = new Staff { Name = "Jack", Age = , Gender = "Male",
DepartmentName = "Personnel Department", BirthDate = new DateTime(,,), EmploymentDate = new DateTime(,,) };
string json = JsonConvert.SerializeObject(jack,new JavaScriptDateTimeConverter());
Console.WriteLine(json);
结果:

现在我们的客户要求出生日期以"ISO"标准日期格式返回,入职日期以Javascript的Date对象格式返回,修改我们的员工类

public class Staff
{
public string Name { get; set; }
public int Age { get; set; }
public string Gender { get; set; }
public string DepartmentName { get; set; }
public Staff Leader { get; set; }
[JsonConverter(typeof(IsoDateTimeConverter))]
public DateTime BirthDate { get; set; }
[JsonConverter(typeof(JavaScriptDateTimeConverter))]
public DateTime EmploymentDate { get; set; }
}

是的,通过特性"JsonConverter"来实现差异化的
序列化:
Staff jack = new Staff { Name = "Jack", Age = , Gender = "Male",
DepartmentName = "Personnel Department", BirthDate = new DateTime(,,), EmploymentDate = new DateTime(,,) };
string json = JsonConvert.SerializeObject(jack);
Console.WriteLine(json);
结果:

客户现在提出要求,希望得到的日期格式是符合中国人习惯的格式.要求返回的格式是"2012年4月20日".挑战来了,没有挑战就没有进步,我喜欢挑战.光说是没有用的!先分析一下怎么解决这个问题.我考虑了两种思路.
思路一:
研究了一下上面两个日期处理类,发现他们都是继承了基类"DateTimeConverterBase",所以我们可以参考"IsoDatetimeConverter"的实现方式,自己新建一个处理日期格式的转换器类.这种方式的缺点是可能要花大量的时间去研究,比较费时费力.优点就是可以对日期格式随心所欲的控制.
思路二:
我又研究了一下"IsoDatetimeConverter",发现它的日期格式其实是由于内部DefaultDateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK"导致,而它也提供了修改日期样式的属性"DateTimeFormat",只要我们按照这种格式来写就OK了.

Staff jack = new Staff { Name = "Jack", Age = , Gender = "Male",
DepartmentName = "Personnel Department", BirthDate = new DateTime(,,), EmploymentDate = new DateTime(,,) };
IsoDateTimeConverter dtConverter = new IsoDateTimeConverter { DateTimeFormat = "yyyy'年'MM'月'dd'日'" };
string json = JsonConvert.SerializeObject(jack,dtConverter);
Console.WriteLine(json);

结果:


public class Person
{
public int Id { get; set; } public string Name { get; set; }
}

默认序列化的结果为: {"Id":1,"Name":"杨过"},如果不想用默认的字段名称,可以使用如下方式:

public class Person
{
[JsonProperty(PropertyName = "PersonId")]
public int Id { get; set; } [JsonProperty(PropertyName = "PersonName")]
public string Name { get; set; }
}

这样序列化的结果为:{"PersonId":1,"PersonName":"杨过"}
Json.Net系列教程 3.Json.Net序列化和反序列化设置的更多相关文章
- Json.Net系列教程 1.Json.Net介绍及实例
原文 Json.Net系列教程 1.Json.Net介绍及实例 本系列教程假设读者已经对Json有一定的了解,关于Json在这里不多说.本系列教程希望能对读者开发涉及到Json的.Net项目有一定的帮 ...
- Json.Net系列教程 2.Net类型与JSON的映射关系
原文 Json.Net系列教程 2.Net类型与JSON的映射关系 首先谢谢大家的支持和关注.本章主要介绍.Net类型与JSON是如何映射的.我们知道JSON中类型基本上有三种:值类型,数组和对象.而 ...
- Json.Net系列教程 4.Linq To JSON
原文 Json.Net系列教程 4.Linq To JSON 更改历史 2013-05-31 添加一个FAQ 一.Linq to JSON是用来干什么的? Linq to JSON是用来操作JSO ...
- JSON和XML格式与对象的序列化及反序列化的辅助类
下面的代码主要是把对象序列化为JSON格式或XML格式等 using System; using System.Collections.Generic; using System.Globalizat ...
- Json.Net学习(1) 实现简单的序列化和反序列化
Attributes 可以用来控制Json.Net如何序列化和反序列化.Net对象. >JsonObjectAttribute--标记在类上,用于控制该类如何被序列化为一个Json对象(JSON ...
- Json.Net序列化和反序列化设置
首先补充一点,Json.Net是支持序列化和反序列化DataTable,DataSet,Entity Framework和NHibernate的.我举例说明DataTable的序列化和反序列化.创建一 ...
- 【json】与【枚举】的序列化和反序列化
参考:Jackson – Deserialization from json to Java enums 问题描述 java中使用枚举时,如果涉及到restful调用,不可避免会涉及到枚举的序列化和反 ...
- c# 通过json.net中的JsonConverter进行自定义序列化与反序列化
https://www.cnblogs.com/yijiayi/p/10051284.html 相信大家在工作中会经常遇见对json进行序列化与反序列化吧,但通常的序列化与反序列化中的json结构与c ...
- [js高手之路] html5 canvas系列教程 - 线形渐变,径向渐变与阴影设置
接着上文[js高手之路] html5 canvas系列教程 - 像素操作(反色,黑白,亮度,复古,蒙版,透明)继续. 一.线形渐变 线形渐变指的是一条直线上发生的渐变. 用法: var linear ...
随机推荐
- 关于HTTP 协议的特点,以及网络请求GET 和 POST 的区别?
HTTP协议有何特点: HTTP 超文本的传输协议,是短连接,是客户端主动发送请求,服务器做出响应,服务器响应之后连接断开 HTTP是属于应用层面向对象的协议,HTTP 有2类报文:请求报文和响应报文 ...
- 【转】在SQL Server 2008中SA密码丢失了怎么办?
sql server 2008的sa用户莫名其妙就登陆不进去了.提示如下: 以上提示就表明是密码错误,但密码我可是记得牢牢的,也许是系统被黑的原因吧.一直以来我的Windows身份验证就用不起,以下方 ...
- js中字符串方法
字符串方法: 1. charAt(索引值)//通过索引值获取字符串中对应的值 例如: var str='sdf123'; alert(str.charAt(0));//结果弹出第一个索引对应的值:s
- HOJ1087
Self Numbers My Tags (Edit) Source : ACM ICPC Mid-Central USA 1998 Time limit : 5 sec Memory ...
- HelloWorld——Cocos2d-x学习历程(二)
HelloWorld分析: 1."resource"文件夹 该文件夹主要用于存放游戏中需要的图片.音频和配置等资源文件. 2."include"和"s ...
- VC++学习之进程和线程的区别
VC++学习之进程和线程的区别 一.进程 进程是表示资源分配的基本单位,又是调度运行的基本单位.例如,用户运行自己的程序,系统就创建一个进程,并为它分配资源,包括各种表格.内存空间.磁盘 ...
- (4)事件处理——(2)在页面加载的时候执行任务(Performing tasks on page load)
We have already seen how to make jQuery react to the loading of a web page. The $(document).ready()e ...
- SQL Server 中大小写区分的处理
SQL Server 中大小写区分的处理. 默认情况下,SQL Server 里面是不区分大小写的: E:\>sqlcmd -S "localhost\SQLEXPRESS" ...
- SpringMVC入门一:helloWorld
玩了一下SpringMVC, 感觉挺清爽的 好像没有struts那么臃肿( 可能是高级的东西我还不会用 哈 ) 例子中一共有俩方法: 一个Controller直接返回字串的方法, 另一个通过Dao层返 ...
- Hibernate 配置详解(12) 补充
hibernate.hbm2ddl.import_files_sql_extractor 这个配置项用于补充这篇文章: http://blog.csdn.net/stefwu/article/deta ...