Ø  前言

说起 C# 对 JSON 的操作(序列化与反序列化),大家都会想到 JavaScriptSerializer、DataContractJsonSerializer 与 Newtonsoft.Json 等。三者都是用于操作 JSON 的框架利器,它们又有什么区别呢?本文包括:

1.   常用 JSON 操作框架(JavaScriptSerializer、DataContractJsonSerializer、Newtonsoft.Json)的区别与比较

2.   简单序列化与反序列化

3.   匿名对象

4.   DataTable

5.   私有成员

6.   指定成员名称

7.   指定序列化成员

8.   枚举类型成员

1.   常用 JSON 操作框架(JavaScriptSerializer、DataContractJsonSerializer、Newtonsoft.Json)的区别与比较

1)   区别如下:

1.   JavaScriptSerializer,位于 System.Web.Extensions.dll 程序集,它是 .NET 自带的程序集,适用于 Web 项目中,因为每当新建一个 Web 项目后,VS 都会自动帮我引用该程序集,

2.   DataContractJsonSerializer,位于 System.Runtime.Serialization.dll 程序集,也是属于 .NET 自带的程序集。适用于 WCF 项目中,因为每当新建一个 WCF 项目后,VS 都会自动帮我引用该程序集。另外,由名称可见它是一种“数据契约 JSON 序列化”。

3.   Newtonsoft.Json,一个第三方的开源类库,主要处理数据的 JSON 序列化操作,在性能或功能方面与前两者相比都有优势,官网:https://www.newtonsoft.com/json,适用于对 JSON 数据操作平凡的各种项目中。

2)   性能比较

1.   下图是 Newtonsoft.Json 官网给出的执行耗时比较

2.   Newtonsoft.Json 官网当然说自己的牛逼,所以,本人在本机进行了代码验证,代码如下:

string jssStr, dcjsStr, jcStr;

Person[] jssArr, dcjsArr, jcArr;

int count = 100000;

Person[] persons = new Person[count];

for (int i = 0; i < count; i++)

{

persons[i] = new Person()

{

Name = string.Format("李三毛_{0}", i),

Age = 29,

Sex = true,

Address = "湖北省利川市",

Spouse = new Person()

{

Name = string.Format("大美妞_{0}", i),

Age = 25,

Sex = false,

Address = "湖北省利川市",

Spouse = null

}

};

}

System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();

//3.1 JavaScriptSerializer

JavaScriptSerializer jss = new JavaScriptSerializer();

jss.MaxJsonLength = 92097152;    //默认为:2097152

stopwatch.Restart();

jssStr = jss.Serialize(persons);

stopwatch.Stop();

Console.WriteLine("JavaScriptSerializer Serialize Time【{0:F1}s,{1}ms】,String Length:{2}",

TimeSpan.FromMilliseconds(stopwatch.ElapsedMilliseconds).TotalSeconds, stopwatch.ElapsedMilliseconds, jssStr.Length);

stopwatch.Restart();

jssArr = jss.Deserialize<Person[]>(jssStr);

stopwatch.Stop();

Console.WriteLine("JavaScriptSerializer Deserialize Time【{0:F1}s,{1}ms】,Array Length:{2}",

TimeSpan.FromMilliseconds(stopwatch.ElapsedMilliseconds).TotalSeconds, stopwatch.ElapsedMilliseconds, jssArr.Length);

//3.2 DataContractJsonSerializer

DataContractJsonSerializer dcjs = new DataContractJsonSerializer(typeof(Person[]));

stopwatch.Restart();

using (MemoryStream stream = new MemoryStream())

{

dcjs.WriteObject(stream, persons);

dcjsStr = Encoding.UTF8.GetString(stream.ToArray());

}

stopwatch.Stop();

Console.WriteLine("DataContractJsonSerializer Serialize Time【{0:F1}s,{1}ms】,String Length:{2}",

TimeSpan.FromMilliseconds(stopwatch.ElapsedMilliseconds).TotalSeconds, stopwatch.ElapsedMilliseconds, dcjsStr.Length);

stopwatch.Restart();

using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(dcjsStr)))

{

dcjsArr = dcjs.ReadObject(stream) as Person[];

}

stopwatch.Stop();

Console.WriteLine("DataContractJsonSerializer Deserialize Time【{0:F1}s,{1}ms】,Array Length:{2}",

TimeSpan.FromMilliseconds(stopwatch.ElapsedMilliseconds).TotalSeconds, stopwatch.ElapsedMilliseconds, dcjsArr.Length);

//3.3 Newtonsoft.Json

stopwatch.Restart();

jcStr = JsonConvert.SerializeObject(persons);

stopwatch.Stop();

Console.WriteLine("Newtonsoft.Json Serialize Time【{0:F1}s,{1}ms】,String Length:{2}",

TimeSpan.FromMilliseconds(stopwatch.ElapsedMilliseconds).TotalSeconds, stopwatch.ElapsedMilliseconds, jcStr.Length);

stopwatch.Restart();

jcArr = JsonConvert.DeserializeObject<Person[]>(jcStr);

stopwatch.Stop();

Console.WriteLine("Newtonsoft.Json Deserialize Time【{0:F1}s,{1}ms】,Array Length:{2}",

TimeSpan.FromMilliseconds(stopwatch.ElapsedMilliseconds).TotalSeconds, stopwatch.ElapsedMilliseconds, jcArr.Length);

Ø  运行结果(三者分别运行三次后的最短耗时)

1.   Serialize(序列化)

1)   DataContractJsonSerializer Serialize Time【0.7s,696ms】,String Length:14377781

2)   Newtonsoft.Json Serialize Time【1.7s,1741ms】,String Length:14377781

3)   JavaScriptSerializer Serialize Time【6.2s,6189ms】,String Length:14377781

2.   Deserialize(反序列化)

1)   DataContractJsonSerializer Deserialize Time【2.0s,2037ms】,Array Length:100000

2)   Newtonsoft.Json Deserialize Time【2.4s,2407ms】,Array Length:100000

3)   JavaScriptSerializer Deserialize Time【3.7s,3733ms】,Array Length:100000

Ø  可见,耗时最短的并不是 Newtonsoft.Json,而是 .NET 自带的 DataContractJsonSerializer,最差的是 JavaScriptSerializer,序列化用了6秒,而 DataContractJsonSerializer 则之需要1秒时间不到。所以这一局,DataContractJsonSerializer 胜出,而 Newtonsoft.Json 则稍微靠后,由于它的功能方面比较强大,所以还是继续研究它。

Ø  首先,我们定义一个测试的类,并创建类的实例和一个匿名对象(后面的示例基本都使用该类)

1.   定义测试类(Goods 为一个部分类)

/// <summary>

/// 商品

/// </summary>

public partial class Goods

{

/// <summary>

/// 商品Id

/// </summary>

public int GoodsId { get; set; }

/// <summary>

/// 商品名称

/// </summary>

public string GoodsName { get; set; }

/// <summary>

/// 价格

/// </summary>

public decimal Price { get; set; }

/// <summary>

/// 是否限购

/// </summary>

public bool IsQuota { get; set; }

/// <summary>

/// 商品属性数组

/// </summary>

public Attribute[] Attributes { get; set; }

/// <summary>

/// 商品属性

/// </summary>

public class Attribute

{

public string Name { get; set; }

public string Value { get; set; }

}

}

2.   创建类的实例

Goods[] goods = new Goods[]

{

new Goods()

{

GoodsId = 1,

GoodsName = "联想ThinkPad无线鼠标",

Price = 125.00m,

IsQuota = true,

Attributes = new Goods.Attribute[]

{

new Goods.Attribute() { Name = "品牌", Value = "Lenovo/联想" },

new Goods.Attribute() { Name = "颜色", Value = "黑色" }

}

}

};

var anonymousGoods = new[]

{

new

{

GoodsId = 2,

GoodsName = "联想ThinkPad无线键盘",

Price = 286.00m,

IsQuota = false,

Attributes = new []

{

new { Name = "品牌", Value = "Lenovo/联想" },

new { Name = "颜色", Value = "白色" }

}

}

};

2.   简单序列化与反序列化

1)   序列化

序列化通常使用 JsonConvert 类的 SerializeObject 方法,该方法有 6 个重载方法,例如:

string jsonStr1_1 = JsonConvert.SerializeObject(goods);

结果:

[{"GoodsId":1,"GoodsName":"联想ThinkPad无线鼠标","Price":125.00,"IsQuota":true,"Attributes":[{"Name":"品牌","Value":"Lenovo/联想"},{"Name":"颜色","Value":"黑色"}]}]

2)   反序列化

序列化通常使用 JsonConvert 类的 DeserializeObject 方法,该方法有 8 个重载方法,例如:

Goods[] jsonObj1_1 = JsonConvert.DeserializeObject<Goods[]>(jsonStr1_1);

结果:

3.   匿名对象

1)   序列化

string jsonStr1_2 = JsonConvert.SerializeObject(anonymousGoods);

结果:

[{"GoodsId":2,"GoodsName":"联想ThinkPad无线键盘","Price":286.00,"IsQuota":false,"Attributes":[{"Name":"品牌","Value":"Lenovo/联想"},{"Name":"颜色","Value":"白色"}]}]

2)   反序列化

var jsonObj1_2 = JsonConvert.DeserializeAnonymousType(jsonStr1_2, anonymousGoods);

结果:

4.   DataTable

首先,创建一个 DataTable 对象并插入数据

DataTable dataTable = new DataTable();

dataTable.Columns.AddRange(new DataColumn[]

{

new DataColumn() { ColumnName = "GoodsId", DataType = typeof(int) },

new DataColumn() { ColumnName = "GoodsName", DataType = typeof(string) },

new DataColumn() { ColumnName = "Price", DataType = typeof(decimal) }

});

for (int i = 0; i < 2; i++)

{

DataRow dataRow = dataTable.NewRow();

dataRow["GoodsId"] = i + 1;

dataRow["GoodsName"] = string.Format("测试商品{0}", i + 1);

dataRow["Price"] = i + 101;

dataTable.Rows.Add(dataRow);

}

1)   序列化

string jsonStr3_1 = JsonConvert.SerializeObject(dataTable);

结果:[{"GoodsId":1,"GoodsName":"测试商品1","Price":101.0},{"GoodsId":2,"GoodsName":"测试商品2","Price":102.0}]

2)   反序列化

DataTable jsonObj3_1 = JsonConvert.DeserializeObject<DataTable>(jsonStr3_1);

结果:

5.   私有成员(以 Price、IsQuota 为例)

Newtonsoft.Json 默认是不处理 private(私有)成员的,如非要处理也是可以的,在私有成员上标记 JsonPropertyAttribute 特性即可,例如(修改 Goods):

private decimal _price = 126;

/// <summary>

/// 价格

/// </summary>

private decimal Price { get { return _price; } set { _price = value; } }

private bool _isQuota = true;

/// <summary>

/// 是否限购

/// </summary>

[JsonProperty]

private bool IsQuota { get { return _isQuota; } set { _isQuota = value; } }

1)   序列化

string jsonStr4_1 = JsonConvert.SerializeObject(goods);

结果:

[{"GoodsId":1,"GoodsName":"联想ThinkPad无线鼠标","IsQuota":true,"Attributes":[{"Name":"品牌","Value":"Lenovo/联想"},{"Name":"颜色","Value":"黑色"}]}]

2)   反序列化

Goods[] jsonObj4_1 = JsonConvert.DeserializeObject<Goods[]>(jsonStr4_1);

结果:

6.   指定成员名称

使用 JsonPropertyAttribute 特性的 PropertyName 属性指定 JSON 成员名称,例如(修改 Goods):

[JsonProperty("att_name")]

public string Name { get; set; }

[JsonProperty("att_val")]

public string Value { get; set; }

1)   序列化

string jsonStr5_1 = JsonConvert.SerializeObject(goods);

结果:

[{"GoodsId":1,"GoodsName":"联想ThinkPad无线鼠标","IsQuota":true,"Attributes":[{"att_name":"品牌","att_val":"Lenovo/联想"},{"att_name":"颜色","att_val":"黑色"}]}]

2)   反序列化

Goods[] jsonObj5_1 = JsonConvert.DeserializeObject<Goods[]>(jsonStr5_1);

结果:

7.   指定序列化成员

Newtonsoft.Json 提供三种序列化模式,使用 Newtonsoft.Json.MemberSerialization 枚举表示。例如(修改 Goods):

[JsonObject(Newtonsoft.Json.MemberSerialization.OptIn)]

public class Goods {...}

/// <summary>

/// 商品名称

/// </summary>

[JsonProperty]

public string GoodsName { get; set; }

OptOut

默认值,序列化所有共有成员,可以使用 JsonIgnore 特性,标记不需要序列化的成员。

OptIn

只序列化标记 JsonProperty 特性的成员。

Fields

只序列化字段成员。注意:默认情况下字段也支持序列化和反序列化。

1)   序列化

string jsonStr6_1 = JsonConvert.SerializeObject(goods);

结果:[{"GoodsName":"联想ThinkPad无线鼠标","IsQuota":true}]

2)   反序列化

Goods[] jsonObj6_1 = JsonConvert.DeserializeObject<Goods[]>(jsonStr6_1);

结果:

8.   枚举类型成员

枚举类型成员默认情况下,是序列化枚举类型的值。如果希望序列化成员名称,需要在成员上标记 JsonConverter 特性,并指定 Newtonsoft.Json.Converters.StringEnumConverter 类型,例如(修改 Goods):

/// <summary>

/// 商品状态

/// </summary>

public enum Status

{

/// <summary>

/// 无

/// </summary>

None = 0,

/// <summary>

/// 上架

/// </summary>

Online = 1,

/// <summary>

/// 下架

/// </summary>

Offline = 2

}

/// <summary>

/// 商品扩展

/// </summary>

public partial class Goods

{

/// <summary>

/// 商品状态

/// </summary>

[JsonProperty]

[JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]

public Status Status { get; set; }

}

1)   序列化

string jsonStr7_1 = JsonConvert.SerializeObject(goods);

结果:[{"GoodsName":"联想ThinkPad无线鼠标","IsQuota":true,"Status":"Online"}]

2)   反序列化

Goods[] jsonObj7_1 = JsonConvert.DeserializeObject<Goods[]>(jsonStr7_1);

结果:

Newtonsoft.Json 的基本用法的更多相关文章

  1. 记录Newtonsoft.Json的日常用法

    最近在做一个使用基于.net mvc 实现前后台传输Json的实例.网上找了一些资料.发现在开发的时候,许多的数据交互都是以Json格式传输的.其中涉及序列化对象的使用的有DataContractJs ...

  2. Newtonsoft.Json 的高级用法

    Ø  简介 接着前一篇http://www.cnblogs.com/abeam/p/8295765.html,继续研究 Newtonsoft.Json 的一些高级用法.主要包括: 1.   JSON ...

  3. Newtonsoft.Json 的解析用法。

    JsonView是查看和分析json的利器,目录下的Newtonsoft.Json.dll ,我们可以当第三方引用之. >>> //想服务器端发送请求,获取订单信息 myReques ...

  4. 记一次 Newtonsoft.Json 巧妙的用法(C#)

    数据添加的功能 有一个表格提交数据如下: 是否选择和文本值.分开保存到数据库太麻烦.取得时候也麻烦 想到了存成json数据.一个字段就可以了. html代码: <table class=&quo ...

  5. Newtonsoft.Json高级用法(转)

    手机端应用讲究速度快,体验好.刚好手头上的一个项目服务端接口有性能问题,需要进行优化.在接口多次修改中,实体添加了很多字段用于中间计算或者存储,然后最终用Newtonsoft.Json进行序列化返回数 ...

  6. 【转】 Newtonsoft.Json高级用法

    手机端应用讲究速度快,体验好.刚好手头上的一个项目服务端接口有性能问题,需要进行优化.在接口多次修改中,实体添加了很多字段用于中间计算或者存储,然后最终用Newtonsoft.Json进行序列化返回数 ...

  7. Newtonsoft.Json高级用法 1.忽略某些属性 2.默认值的处理 3.空值的处理 4.支持非公共成员 5.日期处理 6.自定义序列化的字段名称

    手机端应用讲究速度快,体验好.刚好手头上的一个项目服务端接口有性能问题,需要进行优化.在接口多次修改中,实体添加了很多字段用于中间计算或者存储,然后最终用Newtonsoft.Json进行序列化返回数 ...

  8. 转:Newtonsoft.Json高级用法

    原文地址:http://www.cnblogs.com/yanweidie/p/4605212.html 手机端应用讲究速度快,体验好.刚好手头上的一个项目服务端接口有性能问题,需要进行优化.在接口多 ...

  9. Newtonsoft.Json高级用法,json序列号,model反序列化,支持序列化和反序列化DataTable,DataSet,Entity Framework和Entity,字符串

    原文地址:https://www.cnblogs.com/yanweidie/p/4605212.html 手机端应用讲究速度快,体验好.刚好手头上的一个项目服务端接口有性能问题,需要进行优化.在接口 ...

随机推荐

  1. bzoj2560串珠子(子集dp)

    铭铭有n个十分漂亮的珠子和若干根颜色不同的绳子.现在铭铭想用绳子把所有的珠子连接成一个整体. 现在已知所有珠子互不相同,用整数1到n编号.对于第i个珠子和第j个珠子,可以选择不用绳子连接,或者在ci, ...

  2. [SHOI2001]化工厂装箱员(dp?暴力:暴力)

    118号工厂是世界唯一秘密提炼锎的化工厂,由于提炼锎的难度非常高,技术不是十分完善,所以工厂生产的锎成品可能会有3种不同的纯度,A:100%,B:1%,C:0.01%,为了出售方便,必须把不同纯度 ...

  3. 定时自动从FTP服务器取数据脚本

    环境需求:某些情况下经常需要向FTP服务器取文件,可以用定时任务执行简单脚本自动去取相应文件. 一般用法: ~]# ftp  IP地址  端口 //ftp命令可以通过yum install ftp方式 ...

  4. luogu2643 聪聪可可

    题目链接 题意 其实转化之后的题意就是求出树上有多少条路径长度是3的倍数.求答案的时候只要将这个数字除以总路径数量就行了. 思路 考虑点分治.对于当前子树,分别求出出树中每个点到根的路径长度对\(3\ ...

  5. node.js中的文件系统

    文件打开操作 fs.open(path, flags[, mode], callback) path: <string>|<Buffer>|<URL> flags: ...

  6. springmvc 学习笔记

    @Autowired,@RequestMapping,@RequestParam 使用该注解,引入对象时, 可以省略setter getter.减少代码显示. @AutowiredSimService ...

  7. python爬虫获取图片

    import re import os import urllib #根据给定的网址来获取网页详细信息,得到的html就是网页的源代码 def getHtml(url): page = urllib. ...

  8. 免费馅饼 HDU - 1176 (动态规划)

    都说天上不会掉馅饼,但有一天gameboy正走在回家的小径上,忽然天上掉下大把大把的馅饼.说来gameboy的人品实在是太好了,这馅饼别处都不掉,就掉落在他身旁的10米范围内.馅饼如果掉在了地上当然就 ...

  9. Transactional 事务

    1.事务场景中,抛出异常被catch后,如果需要回滚,一定要手动回滚 其实像第一种try catch这种把整个包裹起来,这种业务方法也就等于脱离了spring事务的管理,因为没有任何异常会从业务方法中 ...

  10. 高级组件——分割面板JSplitPane

    分割面板:JSplitPane(方向),默认水平分割.JSplitPane.HORIZONTAL_SPLIT,JSplitPane.VERTICAL_SPLITJSplitPane(方向,boolea ...