首页 > Web开发 > 详细

序列化效率比拼——谁是最后的赢家Newtonsoft.Json【转】

时间:2017-02-13 17:37:05      阅读:212      评论:0      收藏:0      [点我收藏+]

前言:作为开发人员,对象的序列化恐怕难以避免。楼主也是很早以前就接触过序列化,可是理解都不太深刻,对于用哪种方式去做序列化更是随波逐流 —— 项目中原来用的什么方式照着用就好了。可是这么多年自己对于这东西还是挺模糊的,今天正好有时间,就将原来用过的几种方式总结了下,也算是做一个记录,顺便做了下性能测试。楼主算了下,从使用序列化到现在,用到的无非下面几种方式:(1)JavaScriptSerializer方式;(2)DataContract方式;(3)Newtonsoft.Json.

1、准备工作:要对这三种方式分别作测试,必须要将相应的内库引用进来。

(1)JavaScriptSerializer这个类是.Net内置的,属于System.Web.Script.Serialization这个命名空间下面。需要引用System.Web.Extensions这个dll。

(2)DataContract方式也是.net内置的,主要使用的DataContractJsonSerializer这个类,属于System.Runtime.Serialization.Json这个命名空间。需要引用System.Runtime.Serialization这个dll。

(3)Newtonsoft.Json是第三方的dll,但是Visual Studio 对它做了很好的支持。使用方式有两种:一种是去网上下载最新的dll,然后添加引用即可;第二种是直接使用NuGet安装这个包。方式如下:

技术分享

技术分享

按照步骤安装即可。

2、类库准备完毕,还需要提供几个通用的方法。自己分别封装了JavaScriptSerializer和DataContract方式两个方法,代码如下:

#region DataContract序列化
public static class DataContractExtensions
{
    /// <summary>
    /// 将对象转化为Json字符串
    /// </summary>
    /// <typeparam name="T">对象类型</typeparam>
    /// <param name="instanse">对象本身</param>
    /// <returns>JSON字符串</returns>
    public static string ToJsonString<T>(this T instanse)
    {
        try
        {
            DataContractJsonSerializer js = new DataContractJsonSerializer(typeof(T));
            using (MemoryStream ms = new MemoryStream())
            {
                js.WriteObject(ms, instanse);
                ms.Flush();
                ms.Seek(0, SeekOrigin.Begin);
                StreamReader sr = new StreamReader(ms);
                return sr.ReadToEnd();
            }
        }
        catch
        {
            return String.Empty;
        }
    }
    /// <summary>
    /// 将字符串转化为JSON对象,如果转换失败,返回default(T)
    /// </summary>
    /// <typeparam name="T">对象类型</typeparam>
    /// <param name="s">字符串</param>
    /// <returns>转换值</returns>
    public static T ToJsonObject<T>(this string s)
    {
        try
        {
            DataContractJsonSerializer js = new DataContractJsonSerializer(typeof(T));
            using (MemoryStream ms = new MemoryStream())
            {
                StreamWriter sw = new StreamWriter(ms);
                sw.Write(s);
                sw.Flush();
                ms.Seek(0, SeekOrigin.Begin);
                return (T)js.ReadObject(ms);
            }
        }
        catch
        {
            return default(T);
        }
    }
} 
#endregion
#region JavaScriptSerializer方式序列化
public static class JavascriptExtentions
{
    public static string ToScriptJsonString<T>(this T instanse)
    {
        try
        {
            JavaScriptSerializer js = new JavaScriptSerializer();
            return js.Serialize(instanse);
        }
        catch
        {
            return String.Empty;
        }
    }
    public static T ToScriptJsonObject<T>(this string s)
    {
        try
        {
            JavaScriptSerializer js = new JavaScriptSerializer();
            return js.Deserialize<T>(s);
        }
        catch
        {
            return default(T);
        }
    }
} 
#endregion

至于Newtonsoft.Json,自己有对应的方法,就先不封装了。

还有就是提供测试数据的两个方法:

public static List<Person> GetPersons()
{
    var lstRes = new List<Person>();
    for (var i = 0; i < 50000; i++)
    {
        var oPerson = new Person();
        oPerson.Name = "李雷" + i;
        oPerson.Age = 20;
        oPerson.IsChild = i % 5 == 0 ? true : false;
        oPerson.Test1 = "aaaaaa";
        oPerson.Test2 = i.ToString() ;
        oPerson.Test3 = i.ToString();
        oPerson.Test4 = i.ToString();
        oPerson.Test5 = i.ToString();
        oPerson.Test6 = i.ToString();
        oPerson.Test7 = i.ToString();
        oPerson.Test8 = i.ToString();
        oPerson.Test9 = i.ToString();
        oPerson.Test10 = i.ToString();
        lstRes.Add(oPerson);
    }
    return lstRes;
}
public static DataTable GetDataTable()
{
    var dt = new DataTable("dt");
    dt.Columns.Add("Age", Type.GetType("System.Int32"));
    dt.Columns.Add("Name", Type.GetType("System.String"));
    dt.Columns.Add("Sex", Type.GetType("System.String"));
    dt.Columns.Add("IsChild", Type.GetType("System.Boolean"));
    for (var i = 0; i < 1000; i++)
    {
        DataRow dr = dt.NewRow();
        dr["Age"] = i + 1;
        dr["Name"] = "Name" + i;
        dr["Sex"] = i % 2 == 0 ? "" : "";
        dr["IsChild"] = i % 5 > 0 ? true : false;
        dt.Rows.Add(dr);
    }
    return dt;
}
View Code

3、测试开始之前,先介绍下,本篇测试分别通过强类型对象和若类型的DataTable分别去做序列化和反序列化的测试。测试代码:

static void Main(string[] args)
{
    #region 强类型对象
    var lstRes = GetPersons();
    #region JavaScriptSerializer序列化方式
    var lstScriptSerializeObj = new List<string>();
    Stopwatch sp_script = new Stopwatch();
    sp_script.Start();
    foreach (var oPerson in lstRes)
    {
        lstScriptSerializeObj.Add(oPerson.ToScriptJsonString<Person>());
    }
    sp_script.Stop();
    Console.WriteLine("JavaScriptSerializer序列化方式序列化" + lstScriptSerializeObj.Count + "个对象耗时:" + sp_script.ElapsedMilliseconds + "毫秒");
    lstRes.Clear();
    Stopwatch sp_script1 = new Stopwatch();
    sp_script1.Start();
    foreach (var oFrameSerializeObj in lstScriptSerializeObj)
    {
        lstRes.Add(oFrameSerializeObj.ToScriptJsonObject<Person>());
    }
    sp_script1.Stop();
    Console.WriteLine("JavaScriptSerializer序列化方式反序列化" + lstScriptSerializeObj.Count + "个对象耗时:" + sp_script1.ElapsedMilliseconds + "毫秒");
    #endregion
    #region DataContract序列化方式
    var lstFrameSerializeObj = new List<string>();
    Stopwatch sp = new Stopwatch();
    sp.Start();
    foreach (var oPerson in lstRes)
    {
        lstFrameSerializeObj.Add(oPerson.ToJsonString<Person>());
    }
    sp.Stop();
    Console.WriteLine("DataContract序列化方式序列化" + lstFrameSerializeObj.Count + "个对象耗时:" + sp.ElapsedMilliseconds + "毫秒");
    lstRes.Clear();
    Stopwatch sp1 = new Stopwatch();
    sp1.Start();
    foreach (var oFrameSerializeObj in lstFrameSerializeObj)
    {
        lstRes.Add(oFrameSerializeObj.ToJsonObject<Person>());
    }
    sp1.Stop();
    Console.WriteLine("DataContract序列化方式反序列化" + lstFrameSerializeObj.Count + "个对象耗时:" + sp1.ElapsedMilliseconds + "毫秒"); 
    #endregion
    #region Newtonsoft
    var lstNewtonsoftSerialize = new List<string>();
    Stopwatch sp2 = new Stopwatch();
    sp2.Start();
    foreach (var oPerson in lstRes)
    {
        lstNewtonsoftSerialize.Add(JsonConvert.SerializeObject(oPerson));
    }
    sp2.Stop();
    Console.WriteLine("Newtonsoft.Json方式序列化" + lstNewtonsoftSerialize.Count + "个对象耗时:" + sp2.ElapsedMilliseconds + "毫秒");
    lstRes.Clear();
    Stopwatch sp3 = new Stopwatch();
    sp3.Start();
    foreach (var oNewtonsoft in lstNewtonsoftSerialize)
    {
        lstRes.Add(JsonConvert.DeserializeObject<Person>(oNewtonsoft));
    }
    sp3.Stop();
    Console.WriteLine("Newtonsoft.Json方式反序列化" + lstNewtonsoftSerialize.Count + "个对象耗时:" + sp3.ElapsedMilliseconds + "毫秒"); 
    #endregion
    #endregion
    #region 弱类型DataTable
    /*var dt = GetDataTable();
    #region JavaScriptSerializer序列化方式
    var lstScriptSerializeObj = new List<string>();
    Stopwatch sp_script = new Stopwatch();
    sp_script.Start();
    var strRes = dt.ToScriptJsonString<DataTable>();
    sp_script.Stop();
    Console.WriteLine("JavaScriptSerializer序列化方式序列化" + lstScriptSerializeObj.Count + "个对象耗时:" + sp_script.ElapsedMilliseconds + "毫秒");
    dt.Clear();
    Stopwatch sp_script1 = new Stopwatch();
    sp_script1.Start();
    dt = strRes.ToScriptJsonObject<DataTable>();
    sp_script1.Stop();
    Console.WriteLine("JavaScriptSerializer序列化方式反序列化" + lstScriptSerializeObj.Count + "个对象耗时:" + sp_script1.ElapsedMilliseconds + "毫秒");
    #endregion
    #region DataContract序列化方式
    var lstFrameSerializeObj = new List<string>();
    Stopwatch sp = new Stopwatch();
    sp.Start();
    strRes = dt.ToJsonString<DataTable>();
    sp.Stop();
    Console.WriteLine("DataContract序列化方式序列化" + lstFrameSerializeObj.Count + "个对象耗时:" + sp.ElapsedMilliseconds + "毫秒");
    dt.Clear();
    Stopwatch sp1 = new Stopwatch();
    sp1.Start();
    dt = strRes.ToJsonObject<DataTable>();
    sp1.Stop();
    Console.WriteLine("DataContract序列化方式反序列化" + lstFrameSerializeObj.Count + "个对象耗时:" + sp1.ElapsedMilliseconds + "毫秒");
    #endregion
    #region Newtonsoft
    var lstNewtonsoftSerialize = new List<string>();
    Stopwatch sp2 = new Stopwatch();
    sp2.Start();
    strRes = JsonConvert.SerializeObject(dt);
    sp2.Stop();
    Console.WriteLine("Newtonsoft.Json方式序列化" + lstNewtonsoftSerialize.Count + "个对象耗时:" + sp2.ElapsedMilliseconds + "毫秒");
    dt.Clear();
    Stopwatch sp3 = new Stopwatch();
    sp3.Start();
    dt = JsonConvert.DeserializeObject<DataTable>(strRes);
    sp3.Stop();
    Console.WriteLine("Newtonsoft.Json方式反序列化" + lstNewtonsoftSerialize.Count + "个对象耗时:" + sp3.ElapsedMilliseconds + "毫秒");
    #endregion*/
    #endregion
    Console.ReadLine();
}
View Code

4、测试结果:

先说强类型对象的结果:

(1)集合数量100和1000时,序列化和反序列化三种方式差别不大:

技术分享

技术分享

(2)当超过10000时,

技术分享

技术分享

技术分享

弱类型DataTable的测试结果:

JavaScriptSerializer方式直接报错:

技术分享

DataContract方式需要提供DataTable的表名,序列化得到是DataTable的Xml

技术分享

Newtonsoft.Json方式可以实现和Json数据的序列化和反序列化。

技术分享

5、测试总结:

(1)总的来说,DataContract和Newtonsoft.Json这两种方式效率差别不大,随着数量的增加JavaScriptSerializer的效率相对来说会低些。

(2)对于DataTable的序列化,如果要使用json数据通信,使用Newtonsoft.Json更合适,如果是用xml做持久化,使用DataContract合适。

(3)随着数量的增加JavaScriptSerializer序列化效率越来越低,反序列化和其他两种相差不大。

序列化效率比拼——谁是最后的赢家Newtonsoft.Json【转】

原文:http://www.cnblogs.com/dayang12525/p/6394704.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!