C#中 Json序列化与反序列的几种方法

一、System.Text.Json(微软自带)

      #region using System.Text.Json
      private static string ObjectToStringOne(Object obj)
      {
          string str = System.Text.Json.JsonSerializer.Serialize(obj);
          return str;
      }
      private static T StringToObjectOne<T>(string str)
      {
          T obj = System.Text.Json.JsonSerializer.Deserialize<T>(str);
          return obj;
      }
      #endregion

二、NewTonsoft.Json(包)

      #region using NewTonsoft.Json
      private static string ObjectToStringTwo(Object obj)
      {
          string str = Newtonsoft.Json.JsonConvert.SerializeObject(obj);
          return str;
      }

      private static T StringToObjectTwo<T>(string str)
      {
          T obj = Newtonsoft.Json.JsonConvert.DeserializeObject<T>(str);
          return obj;
      }
      #endregion

三、System.Runtime.Serialization.Json(以数据流为中介)

     #region using System.Runtime.Serialization.Json;
     private static string ObjectToStringThree<T>(Object obj)
     {
         // Object->stream->string
         DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
         MemoryStream ms = new MemoryStream();
         serializer.WriteObject(ms, obj);

         ms.Position = 0;
         StreamReader sr = new StreamReader(ms, Encoding.UTF8);
         string content_josn = sr.ReadToEnd();
         sr.Close();

         return content_josn;
     }
     private static T StringToObjectThree<T>(string str)
     {
         // string->stream->Object
         using (MemoryStream ms2 = new MemoryStream(Encoding.Unicode.GetBytes(str)))
         {
             DataContractJsonSerializer deserializer = new DataContractJsonSerializer(typeof(T));
             T obj = (T)deserializer.ReadObject(ms2);
             return obj;
         }
     }
     #endregion

四、Nancy(包)

     #region using Nancy.Json;
     private static string ObjectToStringFour(Object obj)
     {
         JavaScriptSerializer jss = new JavaScriptSerializer();
         return jss.Serialize(obj);
     }
     private static T StringToObjectFour<T>(string str)
     {
         JavaScriptSerializer jss = new JavaScriptSerializer();
         return jss.Deserialize<T>(str);
     }
     #endregion

五、性能测试

1、使用Bogus生成假数据

	// 生成类
   	[DataContract]
    internal class Person
    {
        [DataMember]
        public Guid Id { get; set; }
        [DataMember]
        public string Name { get; set; }
        [DataMember]
        public string Address { get; set; }
        [DataMember]
        public string Email { get; set; }
    }

	 // Nuget下载Bogus包,引用命名空间,使用Faker创建假数据生成器
     var studentgenerator = new Faker<Person>()
         .RuleFor(o => o.Id, Guid.NewGuid)
         .RuleFor(o => o.Name, f => f.Person.UserName)
         .RuleFor(o => o.Address, f => f.Person.Address.City)
         .RuleFor(o => o.Email, f => f.Person.Email);
     var studentlist = studentgenerator.Generate(100000);

2、序列与反序列单个大对象

	Stopwatch sw = new Stopwatch();
    string str;

    // 微软自带System.Text.Json
    sw.Start();
    str = ObjectToStringOne(studentlist);
    StringToObjectOne<List<Person>>(str);
    sw.Stop();
    Console.WriteLine($"{sw.ElapsedTicks}");

    // Newtonsoft.Json包
    sw.Reset();
    sw.Start();
    str = ObjectToStringTwo(studentlist);
    StringToObjectTwo<List<Person>>(str);
    sw.Stop();
    Console.WriteLine($"{sw.ElapsedTicks}");

    // 数据流System.Runtime.Serialization.Json
    sw.Reset();
    sw.Start();
    str = ObjectToStringThree<List<Person>>(studentlist);
    StringToObjectThree<List<Person>>(str);
    sw.Stop();
    Console.WriteLine($"{sw.ElapsedTicks}");

    // Nancy包
    sw.Reset();
    sw.Start();
    str = ObjectToStringFour(studentlist);
    StringToObjectFour<List<Person>>(str);
    sw.Stop();
    Console.WriteLine($"{sw.ElapsedTicks}");

3、序列与反序列多个小对象

    Stopwatch sw = new Stopwatch();
    string str;
    
    // 微软自带System.Text.Json
    sw.Start();
    foreach(var item in studentlist)
    {
        str = ObjectToStringOne(item);
        StringToObjectOne<Person>(str);
    }
    sw.Stop();
    Console.WriteLine($"{sw.ElapsedTicks}");

    // Newtonsoft.Json包
    sw.Reset();
    sw.Start();
    foreach (var item in studentlist)
    {
        str = ObjectToStringTwo(item);
        StringToObjectTwo<Person>(str);
    }
    sw.Stop();
    Console.WriteLine($"{sw.ElapsedTicks}");

    // 数据流System.Runtime.Serialization.Json
    sw.Reset();
    sw.Start();
    foreach (var item in studentlist)
    {
        str = ObjectToStringThree<Person>(item);
        StringToObjectThree<Person>(str);
    }
    sw.Stop();
    Console.WriteLine($"{sw.ElapsedTicks}");

    // Nancy包
    sw.Reset();
    sw.Start();
    foreach (var item in studentlist)
    {
        str = ObjectToStringFour(item);
        StringToObjectFour<Person>(str);
    }
    sw.Stop();
    Console.WriteLine($"{sw.ElapsedTicks}");

六、测试结果

1. 测试版本

方法 版本
1 .Net Core 3.1
2 13.0.2
3 .Net Core 3.1
4 2.0.0

2. 结果

类数量 序列与反序列单个大对象 序列与反序列多个小对象
1000 4>3>1>2 2>3>4>1
10000 1>3>4>2 2>4=3>1
100000 1>3>2>4 2>3>4>1

3.结论

对应的数据代表方法名,越大代表性能越好用时越短

  1. 在序列与反序列多个小对象的场景下,1方法性能最差,2方法性能最好。
  2. 在序列与反序列多单个大对象的场景下,对象越大,1方法的性能优势越明显,其次是3方法。
  3. 具体使用哪种方法要根据应用场景的对象大小和使用频率决定。

七、参考文章

1.测试方案参考

2.序列化方式参考1

3.序列化方式参考2

4.测试结果参考

5.假数据生成器

6.Bogus的使用方法

你可能感兴趣的:(月刊,json,c#,java)