1. 程式人生 > >序列化效率比拼——誰是最後的贏家Newtonsoft.Json

序列化效率比拼——誰是最後的贏家Newtonsoft.Json

      前言:作為開發人員,物件的序列化恐怕難以避免。樓主也是很早以前就接觸過序列化,可是理解都不太深刻,對於用哪種方式去做序列化更是隨波逐流——專案中原來用的什麼方式照著用就好了。可是這麼多年自己對於這東西還是挺模糊的,今天正好有時間,就將原來用過的幾種方式總結了下,也算是做一個記錄,順便做了下效能測試。樓主算了下,從使用序列化到現在,用到的無非下面幾種方式:(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 class Newtonsoft_Common
    {
        #region 序列化
        // 將物件(包含集合物件)序列化為Json
        public static string SerializeObjToJson(object obj)
        {
            string strRes = string.Empty;
            try
            {
                strRes = JsonConvert.SerializeObject(obj);
            }
            catch 
            { }

            return strRes;
        }

        //將xml轉換為json
        public static string SerializeXmlToJson(System.Xml.XmlNode node)
        {
            string strRes = string.Empty;
            try
            {
                strRes = JsonConvert.SerializeXmlNode(node);
            }
            catch
            { }

            return strRes;
        }

        //支援Linq格式的xml轉換
        public static string SerializeXmlToJson(System.Xml.Linq.XNode node)
        {
            string strRes = string.Empty;
            try
            {
                strRes = JsonConvert.SerializeXNode(node);
            }
            catch
            { }

            return strRes;
        }
        #endregion

        #region 反序列化
        //將json反序列化為實體物件(包含DataTable和List<>集合物件)
        public static T DeserializeJsonToObj<T>(string strJson)
        {
            T oRes = default(T);
            try
            {
                oRes = JsonConvert.DeserializeObject<T>(strJson);
            }
            catch 
            { }

            return oRes;
        }

        //將Json陣列轉換為實體集合
        public static List<T> JsonLstToObjs<T>(List<string> lstJson)
        {
            List<T> lstRes = new List<T>();
            try
            {
                foreach (var strObj in lstJson)
                {
                    //將json反序列化為物件
                    var oRes = JsonConvert.DeserializeObject<T>(strObj);
                    lstRes.Add(oRes);
                }
            }
            catch 
            { }

            return lstRes;
        }
        #endregion
    }

還有就是提供測試資料的兩個方法:

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時,

(3)繼續加大資料量

 

弱型別DataTable的測試結果:

JavaScriptSerializer方式直接報錯:

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

Newtonsoft.Json方式可以實現和Json資料的序列化和反序列化。

5、測試總結:

(1)總的來說,DataContract和Newtonsoft.Json這兩種方式效率差別不大,隨著數量的增加JavaScriptSerializer的效率相對來說會低些。

(2)對於DataTable的序列化,如果要使用json資料通訊,使用Newtonsoft.Json更合適,如果是用xml做持久化,使用DataContract合適。

(3)隨著數量的增加JavaScriptSerializer序列化效率越來越低,反序列化和其他兩種相差不大。

(4)後來發現當物件的DataTime型別屬性不賦值時,DataContract和JavaScriptSerializer這兩種方式序列化都會報錯,而用Newtonsoft.Json方式可以正常序列化。所以看來在容錯方便,還是Newtonsoft.Json比較強。

以上只是樓主自己做的簡單測試,可能存在不夠嚴謹的地方,望各位大蝦拍磚指正~~

附上原始碼:原始碼下載

相關推薦

序列效率——最後贏家Newtonsoft.Json

      前言:作為開發人員,物件的序列化恐怕難以避免。樓主也是很早以前就接觸過序列化,可是理解都不太深刻,對於用哪種方式去做序列化更是隨波逐流——專案中原來用的什麼方式照著用就好了。可是這麼多年自己對於這東西還是挺模糊的,今天正好有時間,就將原來用過的幾種方式總結了下,也算是做一個記錄,順便做了下效能測試

C#基礎系列:序列效率

      前言:作為開發人員,物件的序列化恐怕難以避免。樓主也是很早以前就接觸過序列化,可是理解都不太深刻,對於用哪種方式去做序列化更是隨波逐流——專案中原來用的什麼方式照著用就好了。可是這麼多年自己對於這東西還是挺模糊的,今天正好有時間,就將原來用過的幾種方式總結了下,也算是做一個記錄,順便做了下效能測

Java ObjectOutputStream序列JSON序列

一、背景 有專案需要傳輸Map結構的資料,有人傾向用Java序列化來做,有人傾向用JSON的序列化來做。所以我們還是比比吧。 Java觀點:Object2Object,使用時簡單快速。 JSON觀點:JSON格式與語言無關,擴充套件性強,速度也應該不慢。 大家可能對Java序列化都有

極米皓4K、極米皓、堅果U1、堅果S2四款對比 實際價效比的大更勝一籌

文章轉自:投影網 隨著科技的發展,人們觀看電影的方式不再侷限於電影院,電視機了,因此為了享受生活投影儀應運而生,尤其是近幾年投影儀的發展勢頭尤其猛烈,隨著科技的繼續進步,投影儀的升級版“鐳射電視”正式出現,最近鐳射電視這個詞,又一次重新整理了大眾的視野,因為極米

java序列json序列效率對比

一、背景 有專案需要傳輸Map結構的資料,有人傾向用Java序列化來做,有人傾向用JSON的序列化來做。所以我們還是比比吧。 Java觀點:Object2Object,使用時簡單快速。 JSON觀點:JSON格式與語言無關,擴充套件性強,速度也應該不

gob,protobuf,json在golang中的序列效率對比

先上程式碼:looptimes:=10000 u:=User{66,"nxin","beijing"} gobbegintimestamp:=strconv.FormatInt(time.Now().UTC().UnixNano(), 10) gobbeginint,_

Python3 shevel模塊,更高級的json序列數據類型模塊(pickle更高級)

evel 圖片 alt http python mage 字典 pickle png 直接將數據類型以字典的格式 存到文件中去。 直接.get讀取出來, Python3 shevel模塊,更高級的json序列化數據類型模塊(比pickle更高級)

自行實現dotcore/dotnet更方便更高性能的對象二進制序列

targe restart -a void bubuko ogl mst write PC 二進制序列化可以方便快捷的將對象進行持久化或者網絡傳輸,並且體積小、性能高,應用面甚至還要高於json的序列化;開始之前,先來看看dotcore/dotne自帶的二進

#Java之Object流與序列,看完提高3成開發效率

Object流與序列化 這個也很簡單,java提供了ObjectOutputStream和ObjectInputStream用來對整個物件進行讀寫。 但是記住: (1)物件類必須序列化,即實現Serializable介面,才能整個讀寫。 (2)如果物件的成員變數前加上transien

檔案儲存稱王?雲端儲存效能實測大

如何在大資料時代,又好又快的儲存我們的資料,在這個每天都有海量資料產生的時代,成為了難題。自建儲存的擴張困難、丟失的可能性大的問題,讓雲端儲存成為主流。雲端儲存儲存的資料大多總量巨大,每次搬遷都可能會產生巨大的影響,與其後續不斷搬遷產生巨大影響,何不在一開始就選擇一款物美價廉的雲端儲存服務呢? 今天

並行執行(Callable和Future)一定序列執行效率高嗎?

在一個程式裡順序呼叫了兩個不相關的方法A和B,A耗時100毫秒,B耗時80毫秒,所以總共耗時180毫秒。 main(){ methodA; methodB; } 因為方法A和B不相關,所以我們可以將程式改造成並行執行,使用Callable和Future配合實現(只討論需要A

int 轉 String 的效率

先說一下我自己的實驗結論吧,int 轉 String 的三個方法(假設 x 是int 型變數): ①""+x,效率最低; ②Integer.toString( x ),效率最高; ③String.valueOf( x ),效率比②低一點比①好不少。 詳情如下: 有一

Spark Flink:下一代大資料計算引擎之爭,主沉浮?

下一代大資料計算引擎 自從資料處理需求超過了傳統資料庫能有效處理的資料量之後,Hadoop 等各種基於 MapReduce 的

序列框架的選型和

序列化通訊 將物件轉換為位元組陣列,方便在網路中進行物件的傳輸。在網路通訊中,不同的計算機進行相互通訊主要的方式就是將資料流從一臺機器傳輸給另外一臺計算機,常見的傳輸協議包括了TCP,UDP,HTTP等,網路io的方式主要包括有了aio,bio,nio三種方式。 當客戶端將需要請求的資料封裝好了之後就需要進行

JSON序列,並解碼成為 datagridview 的 datasource

GridView cli obj get connect spa handle string bindings // encode List<clientState> clientList = new List

筆記:I/O流-對象序列

err extends 自己 point clas xtend his size cto Java 語言支持一種稱為對象序列化(Object Serialization)的非常通用的機制,可以將任何對象寫入到流中,並在之後將其讀回,首先需要支持對象

java 對象序列

java 序列化 serializable 對象的序列化:把一個Object對象直接轉化為字節流,然後把它寫入到硬盤上的一個二進制文件或者通過網絡傳輸,同樣的,我們可以把這個二進制文件讀入到內存,然後用來初始化一個對象,需要序列化得類對象,需要實現Serializable接口(空接口,與insta

Protocol buffer序列及其在微信藍牙協議中的應用

number mil 組成 表現 emd 設置 數值 面數據 開發流程 Protocol buffer是Google出品的一種輕便高效的結構化數據存儲格式。可對結構化數據進行序列化,並具有語言無關、平臺無關等特點。在通信協議和數據存儲等領域已經得到廣泛的應

python學習之 -- 數據序列

單獨 get 多次 __main__ print lambda 字典 學習 module json / pickle 數據序列化序列化定義:把變量從內存中變成可存儲或傳輸的過程稱為序列化。反序列化:把變量內容從序列化的對象重新讀到內存裏稱為反序列胡。序列化模塊之--pick

php反序列漏洞繞過魔術方法 __wakeup

prot poc cte enc repo private 成員 .html blank 0x01 前言 前天學校的ctf比賽,有一道題是關於php反序列化漏洞繞過wakeup,最後跟著大佬們學到了一波姿勢。。 0x02 原理 序列化與反序列化簡單介紹 序列化:把復雜的數據