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序列化和反序列化处理(日期时间特殊处理)的更多相关文章

  1. 在net中json序列化与反序列化 面向对象六大原则 (第一篇) 一步一步带你了解linq to Object 10分钟浅谈泛型协变与逆变

    在net中json序列化与反序列化   准备好饮料,我们一起来玩玩JSON,什么是Json:一种数据表示形式,JSON:JavaScript Object Notation对象表示法 Json语法规则 ...

  2. C#中JSON序列化和反序列化

    有一段时间没有到博客园写技术博客了,不过每天逛逛博客园中大牛的博客还是有的,学无止境…… 最近在写些调用他人接口的程序,用到了大量的JSON.XML序列化和反序列化,今天就来总结下json的序列化和反 ...

  3. 在net中json序列化与反序列化

    准备好饮料,我们一起来玩玩JSON,什么是Json:一种数据表示形式,JSON:JavaScript Object Notation对象表示法 Json语法规则: 数据在键值对中 数据由逗号分隔 花括 ...

  4. .Net中json序列化与反序列化

    NuGet中下载Newtonsoft.Json插件. public class JsonHelper<T>{ public static string ModelToJsonString( ...

  5. 转:Json序列化和反序列化

    JSON是专门为浏览器中的网页上运行的JavaScript代码而设计的一种数据格式.在网站应用中使用JSON的场景越来越多,本文介绍 ASP.NET中JSON的序列化和反序列化,主要对JSON的简单介 ...

  6. Scala中使用 Jackson API 进行JSON序列化和反序列化

    1.  什么是 Json 序列化 和 反序列化 序列化 => 将 Java对象 转换成 json字符串反序列化 => 将 json字符串 转换成 Java对象 2. 依赖包 说明 < ...

  7. day5-python中的序列化与反序列化-json&pickle

    一.概述 玩过稍微大型一点的游戏的朋友都知道,很多游戏的存档功能使得我们可以方便地迅速进入上一次退出的状态(包括装备.等级.经验值等在内的一切运行时数据),那么在程序开发中也存在这样的需求:比较简单的 ...

  8. WPF中的常用布局 栈的实现 一个关于素数的神奇性质 C# defualt关键字默认值用法 接口通俗理解 C# Json序列化和反序列化 ASP.NET CORE系列【五】webapi整理以及RESTful风格化

    WPF中的常用布局   一 写在开头1.1 写在开头微软是一家伟大的公司.评价一门技术的好坏得看具体的需求,没有哪门技术是面面俱到地好,应该抛弃对微软和微软的技术的偏见. 1.2 本文内容本文主要内容 ...

  9. 在SpringMVC中,当Json序列化,反序列化失败的时候,会抛出HttpMessageNotReadableException异常, 当Bean validation失败的时候,会抛出MethodArgumentNotValidException异常,因此,只需要在ExceptionHandler类中添加处理对应异常的方法即可。

    在SpringMVC中,当Json序列化,反序列化失败的时候,会抛出HttpMessageNotReadableException异常, 当Bean validation失败的时候,会抛出Method ...

随机推荐

  1. Error -27780: [GENERAL_MSG_CAT_SSL_ERROR]connect to host "124.202.213.70" failed: [10054] Connection reset by peer [MsgId: MERR-27780]

    解决方案一: 备注: 此方案如果请求响应时间太长,勾选"WinInet replay instead of Sockets(Windows only)"将会导致如下错误:

  2. LINUX内核分析第八周学习总结:进程的切换和系统的一般执行过程

    韩玉琪 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.进程切换的关 ...

  3. git init 和 git init --bare 的区别

    http://blog.csdn.net/ljchlx/article/details/21805231 概念  裸仓储 :不可以在上面做git操作    the operation must be ...

  4. NPOI 读写Excel

    实例功能概述: 1.支持Excel2003以及2007 2.支持Excel读取到DataTable(TableToExcel) 3.支持DataTable导出到Excel(TableToExcel) ...

  5. quartus ii13.0~16.0 调用uedit (转载http://blog.sina.com.cn/s/blog_6d5560f00102vax6.html)

    转自 http://blog.sina.com.cn/s/blog_6d5560f00102vax6.html Quartus II 中的文本编辑软件不好用,比较习惯与UE(Uedit32/ultra ...

  6. Kindeditor为什么提交后获取不到值

    LinkButton不是表单提交方式所以获取不到.如果用button submit提交方式就是form提交方式后台就能获取到值 取得编辑器的HTML内容.KindEditor的可视化操作在新创建的if ...

  7. docker 安装

    Docker使用了一种叫AUFS的文件系统,这种文件系统可以让你一层一层地叠加修改你的文件,最底下的文件系统是只读的,如果需要修改文件,AUFS会增加一个可写的层(Layer),这样有很多好处,例如不 ...

  8. struts2 表单验证

    http://www.blogjava.net/javagrass/archive/2011/11/21/364400.html

  9. 云计算和大数据时代网络技术揭秘(八)数据中心存储FCoE

    数据中心存储演化——FCoE   数据中心三大基础:主机 网络 存储 在云计算推动下,存储基础架构在发生演变 传统存储结构DAS.SAN在发展中遇到了布线复杂.能耗增多的缺点(原生性),需要对架构做根 ...

  10. StringGrid 实例2:1、获取 StringGrid 的行数、列数; 2、给单元赋值.

    实例2: 本例功能: 1.获取 StringGrid 的行数.列数; 2.给单元赋值. 运行效果图: