• 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; }
        }
    }
    View Code

      笔者这里先贴出序列化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[0].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

  • 相关阅读:
    利用索引提高SQL Server数据处理的效率
    拆掉思维里的墙摘抄
    QR码和PDF417比较
    保存一个记录到数据库又马上返回ID号
    C#获取当前路径的7种方法
    汉诺塔算法不错,收藏了!
    如何确定Z检验的值(查正态分布表时要注意中间的数字都是面积,最左边一列和最上面一行都是Z值)
    opencv的安装
    SQL事务
    重大财务决策前的思考
  • 原文地址:https://www.cnblogs.com/luge/p/Net_Json_Serialize.html
Copyright © 2020-2023  润新知