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. 使用sessionStorage、localStorage存储数组与对象(转)

    http://my.oschina.net/crazymus/blog/371757 使用sessionStorage.localStorage存储数组与对象 发表于3个月前(2015-01-26 1 ...

  2. clang format 官方文档自定义参数介绍(中英文)

    官方文档:http://clang.llvm.org/docs/ClangFormatStyleOptions.html 中文 在代码中配置样式 当使用 clang::format::reformat ...

  3. Oracle 包(Package)

    引用这位大大的: http://www.cnblogs.com/lovemoon714/archive/2012/02/29/2373695.html 1.为什么要使用包?       答:在一个大型 ...

  4. 遇到的check the manual that corresponds to your MySQL server version for the right syntax错误

    遇到的check the manual that corresponds to your MySQL server version for the right syntax错误. 结果发现是SQL关键 ...

  5. pdflatex, xelatex, texstudio中文编码问题

    使用xelatex,源文件需要用utf-8编译,pdf文件不会乱码. 使用pdflatex,源文件不能使用utf-8编码,否则pdf文件会乱码. 使用GB2312没问题.

  6. jQuery学习实用记录

    //jQuery加载 $(document).ready(function(){ //开始编写函数 }); //点击后 上下滑动隐藏效果 $("#id").click(functi ...

  7. vb.net加密解密方法

    1.vb.net加密解密方法 Private Function getLicenseDate() As String Dim b() As Byte Dim path As String = Serv ...

  8. Linux聊天室项目 -- ChatRome(select实现)

    序 项目简介:采用I/O复用技术select实现socket通信,采用多线程负责每个客户操作处理,完成Linux下的多客户聊天室! OS:Ubuntu 15.04 IDE:vim gcc make D ...

  9. 树状DP (poj 2342)

    题目:Anniversary party 题意:给出N各节点的快乐指数,以及父子关系,求最大快乐指数和(没人职员愿意跟直接上司一起玩): 思路:从底向上的树状DP: 第一种情况:第i个员工不参与,F[ ...

  10. ARP协议

    ARP协议就是一个获取对方MAC地址的协议,ARP协议它是一个网络层的协议,它的作用是通过ARP request报文来获得对方的MAC地址,ARP报文里面发送的内容大概是192.168.1.20你的M ...