Net中JSON序列化和反序列化处理(日期时间特殊处理)
0 缘由
笔者最近在web api端使用Json.Net进行序列化处理,而在调用端使用DataContractSerializer进行反序列化,遇到日期时间处理反序列化不成功【备注:笔者使用Net Framework 4.0】。究其原因,Json.Net默认的日期输出是ISO标准时间,而微软默认的输出与解析日期格式是/Date(1242357713797+0800)/。可以看出我们只需将ISO的标准时间转换成微软能够识别日期时间格式即可。最后笔者就想重新对比下Net中Json序列化和反序列化的三种处理方式,以及性能。
1 介绍
Net中Json序列化反序列化一般常用的有三种:
- JavaScriptSerializer[位于程序集:System.Web.Extension.dll,命令空间:System.Web.Script.Serialization]
- DataContractSerializer[位于程序集:System.Runtime.Serialization.dll,命名空间:System.Runtime.Serialization.Json]
- JsonConvert[位于程序集:Newtonsoft.Json.dll,命名空间:Newtonsoft.Json],外部引用库,可通过Nuget进行获取Json.Net
笔者将分别对这三种进行序列化与反序列化复杂对象,使用Stopwatch进行监测其运行的时间。对比Stopwatch的运行时间,从而得出性能较佳的序列化Json的实现
2 三者对比
新建一个Mvc3.0 项目命名为JsonConvertSample,使用Nuget引入Json.Net(在程序包管理器控制台键入:Install-Package Newtonsoft.Json),准备一个复杂类User,以及对比类JsonCompare。主要代码如下:
//=====================================================
//Copyright (C) www.cnblogs.com/luge
//All rights reserved
//文件名: JsonCompare
//创建时间: 2015-06-21
//当前登录用户名: 卤鸽
//描述:
//====================================================== namespace JsonConvertSample.Models
{
public class JsonCompare
{
public double DataContractSerializeTime { get; set; } public string DcsString { get; set; } public double JavascriptSerializeTime { get; set; } public string jsString { get; set; } public double JsonNetTime { get; set; } public string jnString { get; set; } public int Capacity { get; set; }
} } namespace JsonConvertSample.Models
{
public class User
{ public int UserID { get; set; } public string UserName { get; set; } public decimal Saraly { get; set; } public Address Location { get; set; } public List<School> Schools { get; set; } public DateTime BirthDate { get; set; }
} public class Address
{
public string Province { get; set; } public string City { get; set; }
} public class School
{
public string SchoolName { get; set; } public string SchoolDesc { get; set; }
}
}
笔者这里先贴出序列化Json三种不同的泛型实现(详细可下载源码查看)
#region DataContractJsonSerializer
/// <summary>
/// 序列化json字符串
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj"></param>
/// <param name="datetimePattern"> 替换Json的Date字符串 </param>
/// <returns></returns>
public static string SerializeByContract<T>(T obj, string datetimePattern = null)
where T : class
{
string jsonString = string.Empty;
if (obj == null)
return jsonString;
var ser = new DataContractJsonSerializer(typeof(T));
using (var ms = new MemoryStream())
{
ser.WriteObject(ms, obj);
jsonString = Encoding.UTF8.GetString(ms.ToArray());
}
if (!string.IsNullOrEmpty(datetimePattern))
{
MatchEvaluator matchEvaluator = new MatchEvaluator(ConvertJsonDateToDateString);
Regex reg = new Regex(datetimePattern);
jsonString = reg.Replace(jsonString, matchEvaluator);
}
return jsonString;
}
/// <summary>
/// json反序列化成对象
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="jsonString"></param>
/// <param name="datetimePattern">匹配时间的正则表达式</param>
/// <returns></returns>
public static T DeserializeByContract<T>(string jsonString, string datetimePattern = null)
where T : class
{
if (string.IsNullOrEmpty(jsonString))
{
return default(T);
}
if (!string.IsNullOrEmpty(datetimePattern))
{
MatchEvaluator matchEvaluator = new MatchEvaluator(ConvertDateStringToJsonDate);
var reg = new Regex(datetimePattern);
jsonString = reg.Replace(jsonString, matchEvaluator);
}
var ser = new DataContractJsonSerializer(typeof(T));
var jsonByteArr = Encoding.UTF8.GetBytes(jsonString);
using (var ms = new MemoryStream(jsonByteArr))
{
object obj = ser.ReadObject(ms);
return obj as T;
}
}
#endregion
#region JavaScriptSerializer
public static string SerializeByJavaScript<T>(T obj)
where T : class
{
var jsonString = string.Empty;
if (obj == null)
{
return jsonString;
}
JavaScriptSerializer js = new JavaScriptSerializer();
//<!--进行序列化或反序列化时出错。字符串的长度超过了为 maxJsonLength 属性设置的值-->
js.MaxJsonLength = int.MaxValue;
jsonString = js.Serialize(obj);
return jsonString;
}
public static T DeserializeByJavaScript<T>(string jsonString)
where T : class
{
T obj;
if (string.IsNullOrEmpty(jsonString))
{
obj = null;
return obj;
}
JavaScriptSerializer js = new JavaScriptSerializer();
js.MaxJsonLength = int.MaxValue;
obj = js.Deserialize<T>(jsonString);
return obj;
}
#endregion
#region Json.Net
public static string SerializeByJsonNet<T>(T obj)
where T : class
{
var jsonString = string.Empty;
if (obj == null)
return jsonString;
jsonString = JsonConvert.SerializeObject(obj);
return jsonString;
}
public static T DeserializeByJsonNet<T>(string jsonString)
where T : class
{
T obj = null;
if (string.IsNullOrEmpty(jsonString))
{
return obj;
}
obj = JsonConvert.DeserializeObject<T>(jsonString);
return obj;
}
#endregion
测试代码局部代码(详细可下载源码查看):
Stopwatch sw = new Stopwatch();
sw.Start(); jsonCompare.DcsString = JsonFormat.SerializeByContract<IList<User>>(list); sw.Stop();
jsonCompare.DataContractSerializeTime = sw.ElapsedTicks;
根据不同方式序列化Json得出的结果

由上面的图片结果可以得出结论:Json.Net 优于 DataContractSerialize, DataContractSerialize 优于 JavaScriptSerialize,而且Json.Net甩JavaScriptSerialize几大街。
4、日期时间的处理
本文篇头对笔者遇到的问题已经提出处理方案。针对DataContractSerializer进行反序列化日期时间(由json.net序列化)的处理,如果在Net4.0中,正则表达式匹配对日期类型统一替换即可实现之;当然在Net4.5解决方法就更加简单,只需如下设置,即可完成反序列化json。核心处理代码如下:
#if Net45
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T), new DataContractJsonSerializerSettings()
{
DateTimeFormat = new DateTimeFormat("yyyy-MM-dd'T'HH:mm:ss")
});
#endif
#if Net40
private static string ConvertDateStringToJsonDate(Match m)
{
string result = string.Empty;
DateTime dt = DateTime.Parse(m.Groups[].Value);
dt = dt.ToUniversalTime(); TimeSpan ts = dt - DateTime.Parse("1970-01-01");
result = string.Format("\\/Date({0}+0800)\\/",ts.TotalMilliseconds.ToString("f0"));
return result;
}
string datetimePattern="(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)(?:([\+-])(\d{2})\:(\d{2}))?Z?";
MatchEvaluator matchEvaluator = new MatchEvaluator(ConvertDateStringToJsonDate);
var reg = new Regex(datetimePattern);
jsonString = reg.Replace(jsonString, matchEvaluator);
#endif
5、总结与源码
- JavaScriptSerialize如果序列化对象过大时将会出现“进行序列化或反序列化时出错。字符串的长度超过了为 maxJsonLength 属性设置的值”,只需设置MaxJsonLength=int.MaxValue
- 源码(如果觉得不错请点赞下,有误的话请指出,卤鸽在此感谢)
参考:
http://blog.csdn.net/cncdns/article/details/6164389
Net中JSON序列化和反序列化处理(日期时间特殊处理)的更多相关文章
- 在net中json序列化与反序列化 面向对象六大原则 (第一篇) 一步一步带你了解linq to Object 10分钟浅谈泛型协变与逆变
在net中json序列化与反序列化 准备好饮料,我们一起来玩玩JSON,什么是Json:一种数据表示形式,JSON:JavaScript Object Notation对象表示法 Json语法规则 ...
- C#中JSON序列化和反序列化
有一段时间没有到博客园写技术博客了,不过每天逛逛博客园中大牛的博客还是有的,学无止境…… 最近在写些调用他人接口的程序,用到了大量的JSON.XML序列化和反序列化,今天就来总结下json的序列化和反 ...
- 在net中json序列化与反序列化
准备好饮料,我们一起来玩玩JSON,什么是Json:一种数据表示形式,JSON:JavaScript Object Notation对象表示法 Json语法规则: 数据在键值对中 数据由逗号分隔 花括 ...
- .Net中json序列化与反序列化
NuGet中下载Newtonsoft.Json插件. public class JsonHelper<T>{ public static string ModelToJsonString( ...
- 转:Json序列化和反序列化
JSON是专门为浏览器中的网页上运行的JavaScript代码而设计的一种数据格式.在网站应用中使用JSON的场景越来越多,本文介绍 ASP.NET中JSON的序列化和反序列化,主要对JSON的简单介 ...
- Scala中使用 Jackson API 进行JSON序列化和反序列化
1. 什么是 Json 序列化 和 反序列化 序列化 => 将 Java对象 转换成 json字符串反序列化 => 将 json字符串 转换成 Java对象 2. 依赖包 说明 < ...
- day5-python中的序列化与反序列化-json&pickle
一.概述 玩过稍微大型一点的游戏的朋友都知道,很多游戏的存档功能使得我们可以方便地迅速进入上一次退出的状态(包括装备.等级.经验值等在内的一切运行时数据),那么在程序开发中也存在这样的需求:比较简单的 ...
- WPF中的常用布局 栈的实现 一个关于素数的神奇性质 C# defualt关键字默认值用法 接口通俗理解 C# Json序列化和反序列化 ASP.NET CORE系列【五】webapi整理以及RESTful风格化
WPF中的常用布局 一 写在开头1.1 写在开头微软是一家伟大的公司.评价一门技术的好坏得看具体的需求,没有哪门技术是面面俱到地好,应该抛弃对微软和微软的技术的偏见. 1.2 本文内容本文主要内容 ...
- 在SpringMVC中,当Json序列化,反序列化失败的时候,会抛出HttpMessageNotReadableException异常, 当Bean validation失败的时候,会抛出MethodArgumentNotValidException异常,因此,只需要在ExceptionHandler类中添加处理对应异常的方法即可。
在SpringMVC中,当Json序列化,反序列化失败的时候,会抛出HttpMessageNotReadableException异常, 当Bean validation失败的时候,会抛出Method ...
随机推荐
- Spring 4集成 Quartz2(转)
本文将演示如何通过 Spring 使用 Quartz Scheduler 进行任务调度.Spring 为简化 Quartz 的操作提供了相关支持类.本文示例使用的相关工具如下: Spring 4.2. ...
- 【C#】 目前的技能点
[C#] 目前的技能点 一. C/S 1. WinForm 2. WPF 二.B/S 1. MVC 2. ASPX 3. WebService 4. js 5. jQuery , jQuery UI ...
- OpenSSL命令---passwd
NAME passwd - compute password hashes SYNOPSIS openssl passwd [-crypt] [-1] [-apr1] [-salt string] [ ...
- [2015hdu多校联赛补题]hdu5348 MZL's endless loop
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5348 题意:给你一个无向图,要你将无向图的边变成有向边,使得得到的图,出度和入度差的绝对值小于等于1, ...
- CF(协同过滤算法)
1 集体智慧和协同过滤 1.1 什么是集体智慧(社会计算)? 集体智慧 (Collective Intelligence) 并不是 Web2.0 时代特有的,只是在 Web2.0 时代,大家在 Web ...
- Java中abstract的用法
1,abstract修饰类,会使这个类成为一个抽象类,这个类将不能生成对象实例,可以做为对象变量声明的类型,也就是编译时类型,抽象类就像当于一类的半成品,需要子类继承并覆盖其中的抽象方法. 2,abs ...
- (引用)web安全测试
转载:http://www.51testing.com/html/44/15020244-908645.html Web安全测试之XSS XSS 全称(Cross Site Scripting) 跨站 ...
- div box container随主体内容自动扩展适应的实现
/**顶部部分*/ .con-tl{ background:url(../images/left.png) no-repeat 0 0 rgba(0, 0, 0, 0); padding-left: ...
- MySQL数据库指定字符集
mysql 创建数据库时指定编码很重要,很多开发者都使用了默认编码,但是我使用的经验来看,制定数据库的编码可以很大程度上避免倒入导出带来的乱码问题. 我们遵循的标准是,数据库,表,字段和页面或文本的编 ...
- Linux命令小结:fdisk
查看分区信息 分区信息包括容量.扇区数目.柱面数目.磁头数目和IO大小等信息. root@cvm:/# fdisk -l /dev/sda7 Disk /dev/sda7: 441.8 GB, 441 ...