C#技术栈入门到精通系列6——序列化&反序列化

阅读目录

1、介绍

2、二进制序列化&反序列化

  2.1、二进制序列化&反序列化介绍

  2.2、BinaryFormatter使用

  2.3、自定义序列化

3、XML序列化&反序列化

  3.1、XML序列化&反序列化介绍

  3.2、XmlSerializer使用

  3.3、控制 XML 序列化的属性

  3.4、重写默认序列化逻辑

  3.5、将对象序列化为SOAP编码的XML流

4、JSON序列化&反序列化

  4.1、JSON序列化  

  4.2、使用System.Text.Json序列化&反序列化

  4.3、使用Newtonsoft.Json序列化&反序列化

  4.4、System.Text.Json和Newtonsoft.Json的一些差异

5、参考

返回系列文章目录 

案例代码下载

1、介绍

  序列化:将对象的状态信息及类型信息,转换为一种易于传输或存储形式(流,即字节序列)的过程。

  反序列化:与序列化相反,将流转换为对象的过程。

.NET有以下序列化技术:

二进制序列化:保持类型保真,这对于多次调用应用程序时保持对象状态非常有用。 例如,通过将对象序列化到剪贴板,可在不同的应用程序之间共享对象。 您可以将对象序列化到流、磁盘、内存和网络等。 远程处理使用序列化,“按值”在计算机或应用程序域之间传递对象。

XML和SOAP序列化:只序列化公共属性和字段,并且不保持类型保真。 当您希望提供或使用数据而不限制使用该数据的应用程序时,这一点非常有用。 由于 XML 是开放式的标准,因此它对于通过 Web 共享数据来说是一个理想选择。 SOAP 同样是开放式的标准,这使它也成为一个理想选择。

JSON序列化:只序列化公共属性,并且不保持类型保真。 JSON 是开放式的标准,对于通过 Web 共享数据来说是一个理想选择。

2、二进制序列化&反序列化

2.1、二进制序列化&反序列化介绍

  二进制序列化是将.NET对象转换为数据流,存放到内存中。需要注意两点:①二进制序列化的时候,可以将对象的所有属性进行序列化,包括私有属性。②在反序列化的时候,不会调用无参的构造函数,可以借用这点来进行对象的深拷贝。序列化和反序列化可以通过BinaryFormatter类来实现的,这个类位于System.Runtime.Serialization.Formatters.Binary命名空间下。要使一个类能够序列化,需要使用Serializable属性标记类,如果不想被二进制序列化,在属性字段上使用NonSerialized标记。

 

2.2、BinaryFormatter使用

 1 [Serializable]
 2     public class SerializeObject
 3     {
 4         public string Name { get; set; }
 5         //二进制序列化会把所有的属性字段都序列化,包括私有private,
 6         //如果不想序列化,使用特性[NonSerialized]
 7         private string _desc { get; set; }
 8         public int _Age;
 9         [NonSerialized]
10         private bool _sex;
11         public SerializeObject(string name,string desc,int age,bool sex)
12         {
13             this.Name = name;
14             this._desc = desc;
15             this._Age = age;
16             this._sex = sex;
17         }
18     }
SerializeObject
 1         static void Main(string[] args)
 2         {
 3             SerializeObject serializeObject = new SerializeObject("BigBox777","永远18岁",18,true);
 4             BinaryFormatter formatter = new BinaryFormatter();
 5             using (Stream stream=new FileStream("MyFile.bin",FileMode.OpenOrCreate,FileAccess.Write,FileShare.None))
 6             {
 7                 formatter.Serialize(stream, serializeObject);
 8 
 9                 Console.WriteLine(stream.Length);
10             }
11 
12             Console.ReadLine();
13         }    
二进制序列化代码
 1 //反序列化代码
 2 BinaryFormatter formatter = new BinaryFormatter();
 3 using (Stream stream = new FileStream("MyFile.bin", FileMode.Open, FileAccess.Read, FileShare.None))
 4 {
 5     var obj = formatter.Deserialize(stream);
 6     if(obj is SerializeObject)
 7     {
 8         var serializeObject = (SerializeObject)obj;
 9     }
10 }
11 Console.ReadLine();
二进制反序列化

2.3、自定义序列化

  在序列化期间或者序列化之后可以运行自定义方法。最佳做法是,在需要执行的方法使用特定的属性进行标记。

  • OnDeserializedAttribute:反序列化之后执行
  • OnDeserializingAttribute:反序列化的时候执行
  • OnSerializedAttribute:序列化完成后执行
  • OnSerializingAttribute:执行序列化的时候执行
 1 [Serializable]
 2 public class CustomerSerialize
 3 {
 4     public string Name { get; set; }
 5     //二进制序列化会把所有的属性字段都序列化,包括私有private,
 6     //如果不想序列化,使用特性[NonSerialized]
 7     private string _desc { get; set; }
 8     public int _Age;
 9     [NonSerialized]
10     private bool _sex;
11     public CustomerSerialize(string name, string desc, int age, bool sex)
12     {
13         this.Name = name;
14         this._desc = desc;
15         this._Age = age;
16         this._sex = sex;
17     }
18     [OnSerializing] //序列化的时候执行
19     public void OnSerializingMothed(StreamingContext context)
20     {
21         Console.WriteLine("序列化的时候执行");
22     }
23     [OnSerialized]  //序列化完成后执行
24     public void OnSerializedMothed(StreamingContext context)
25     {
26         Console.WriteLine("序列化完成后执行");
27     }
28     [OnDeserializing]   //反序列化的时候执行
29     public void OnDeserializingMothed(StreamingContext context)
30     {
31         Console.WriteLine("反序列化的时候执行");
32     }
33         [OnDeserialized]    //反序列化完成执行
34     public void OnDeserializedMothed(StreamingContext context)
35     {
36         Console.WriteLine("反序列化完成执行");
37     }
38 }    
CustomerSerialize对象
1 //自定义序列化
2 CustomerSerialize customerSerialize = new CustomerSerialize("BigBox777", "永远18岁", 18, true);
3 BinaryFormatter formatter = new BinaryFormatter();
4 using (Stream stream = new FileStream("MyFile.bin", FileMode.OpenOrCreate, FileAccess.Write, FileShare.None))
5 {
6     formatter.Serialize(stream, customerSerialize);
7     Console.WriteLine(stream.Length);
8 }
9 Console.ReadLine();
序列化
 1 //自定义反序列化
 2 BinaryFormatter formatter = new BinaryFormatter();
 3 using (Stream stream = new FileStream("MyFile.bin", FileMode.Open, FileAccess.Read, FileShare.None))
 4 {
 5     var obj = formatter.Deserialize(stream);
 6     if (obj is CustomerSerialize)
 7     {
 8         var customerSerialize = (CustomerSerialize)obj;
 9     }
10 }
11 Console.ReadLine();
反序列化

3、XML序列化&反序列化

3.1、XML序列化&反序列化介绍

  XML 序列化是将对象的公共属性 (Property) 和字段转换为序列格式(这里是指 XML)以便存储或传输的过程。反序列化则是从 XML 输出中重新创建原始状态的对象。因此,可以将序列化视为将对象的状态保存到流或缓冲区的方法。序列化和反序列化通过XmlSerializer 类来实现的,这个类位于System.Xml.Serialization命名空间下。注意:①XML序列化不转换方法、索引器、私有字段或只读属性(只读集合除外)。要序列化对象的所有字段和属性(公共的和私有的),请使用 BinaryFormatter。②被序列化对象一定要有无参构造函数。

3.2、XmlSerializer使用

 1 using System;
 2 using System.Xml.Serialization;
 3 
 4 namespace Demo06_XmlSerializer
 5 {
 6     [Serializable]
 7     public class SerializeObject
 8     {
 9         public string Name { get; set; }
10         public int _Age;
11         public MyObject MyObjectDate { get; set; }
12         [XmlIgnore]  //加特性后不进行序列化
13         public int Count { get; set; }
14         private bool _sex; //私有属性字段不序列化
15         public SerializeObject(string name, int age, bool sex)
16         {
17             this.Name = name;
18             this._Age = age;
19             this._sex = sex;
20             this.MyObjectDate=new MyObject() { CreateTime = DateTime.Now };
21         }
22         public SerializeObject() //序列化的时候必须要无参的构造函数
23         {
24 
25         }
26     }
27     public class MyObject
28     {
29         public DateTime CreateTime { get; set; }
30     }
31 }
序列化对象SerializeObject
 1 using System;
 2 using System.IO;
 3 using System.Xml.Serialization;
 4 
 5 namespace Demo06_XmlSerializer
 6 {
 7     internal class Program
 8     {
 9         static void Main(string[] args)
10         {
11             //XML序列化
12             SerializeObject serializeObject = new SerializeObject("BigBox777", 18, true);
13             using (StreamWriter myWriter = new StreamWriter("myFileName.xml"))
14             {
15                 XmlSerializer xmlSerializer = new XmlSerializer(typeof(SerializeObject));
16                 xmlSerializer.Serialize(myWriter, serializeObject);
17             }
18 
19             ////XML反序列化
20             //var mySerializer = new XmlSerializer(typeof(SerializeObject));
21             //using (var myFileStream = new FileStream("myFileName.xml", FileMode.Open))
22             //{
23             //    var myObject = (SerializeObject)mySerializer.Deserialize(myFileStream);
24             //}
25 
26             Console.ReadLine();
27         }
28     }
29 }
序列化反序列化代码
1 <?xml version="1.0" encoding="utf-8"?>
2 <SerializeObject xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
3   <_Age>18</_Age>
4   <Name>BigBox777</Name>
5   <MyObjectDate>
6     <CreateTime>2021-12-11T16:56:06.9724693+08:00</CreateTime>
7   </MyObjectDate>
8 </SerializeObject>
序列化结果文件myFileName.xml

3.3、控制 XML 序列化的属性

   通过将下表中的特性应用于类和类成员,可以控制 XmlSerializer 序列化或反序列化该类的实例的方式。 这些属性还可用于控制 XML Web services 生成的文本样式的 SOAP 消息。除了这些特性(全部位于 System.Xml.Serialization 命名空间中)之外,还可以将 DefaultValueAttribute 特性应用于字段。 如果没有指定值,使用 DefaultValueAttribute 可设置将自动分配给成员的值。

特性适用对象指定
XmlAnyAttributeAttribute 公共字段、属性、参数或返回 XmlAttribute 对象数组的返回值。 反序列化时,将会使用 XmlAttribute 对象填充数组,而这些对象代表对于架构未知的所有 XML 特性。
XmlAnyElementAttribute 公共字段、属性、参数或返回 XmlElement 对象数组的返回值。 反序列化时,将会使用 XmlElement 对象填充数组,而这些对象代表对于架构未知的所有 XML 元素。
XmlArrayAttribute 公共字段、属性、参数或返回复杂对象的数组的返回值。 数组成员将作为 XML 数组的成员生成。
XmlArrayItemAttribute 公共字段、属性、参数或返回复杂对象的数组的返回值。 可以插入数组的派生类型。 通常与 XmlArrayAttribute 一起应用。
XmlAttributeAttribute 公共字段、属性、参数或返回值。 成员将作为 XML 属性进行序列化。
XmlChoiceIdentifierAttribute 公共字段、属性、参数或返回值。 可以使用枚举进一步消除成员的歧义。
XmlElementAttribute 公共字段、属性、参数或返回值。 字段或属性将作为 XML 元素进行序列化。
XmlEnumAttribute 作为枚举标识符的公共字段。 枚举成员的元素名称。
XmlIgnoreAttribute 公共属性和公共字段。 序列化包含类时,应该忽略属性或字段。
XmlIncludeAttribute 公共派生类声明,以及 Web 服务描述语言 (WSDL) 文档的公共方法的返回值。 生成要在序列化时识别的架构时,应该将该类包括在内。
XmlRootAttribute 公共类声明。 控制视为 XML 根元素的属性目标的 XML 序列化。 使用该属性可进一步指定命名空间和元素名称。
XmlTextAttribute 公共属性和公共字段。 属性或字段应该作为 XML 文本进行序列化。
XmlTypeAttribute 公共类声明。 XML 类型的名称和命名空间。

3.4、使用 XmlAttributeOverrides 类重写序列化逻辑

  案例是序列化一个名为 Orchestra(管弦乐队) 的类,该类包含一个名为 Instruments(乐器) 的字段,该字段 Instruments 返回对象的数组 Instrument(乐器) 类 。 名为 Brass(铜管乐器) 的第二个类  从 Instrument 类继承。 该示例使用类的实例 XmlAttributeOverrides 来重写 Instrument 字段,允许字段接受 Brass 对象。

 1 namespace Demo06_OverwriteXmlSerializer
 2 {
 3     /// <summary>
 4     /// 管弦乐队
 5     /// </summary>
 6     public class Orchestra
 7     {
 8         public Instrument[] Instruments;
 9     }
10     /// <summary>
11     /// 乐器
12     /// </summary>
13     public class Instrument
14     {
15         public string Name;
16     }
17     /// <summary>
18     /// 铜管乐器
19     /// </summary>
20     public class Brass: Instrument
21     {
22         public bool IsValved;
23     }
24 }
序列化对象
  1 using System;
  2 using System.IO;
  3 using System.Xml.Serialization;
  4 
  5 namespace Demo06_OverwriteXmlSerializer
  6 {
  7     internal class Program
  8     {
  9         static void Main(string[] args)
 10         {
 11             Program test = new Program();
 12             test.SerializeObject("Override.xml");
 13             test.DeserializeObject("Override.xml");
 14         }
 15         public void SerializeObject(string filename)
 16         {
 17             
 18             XmlAttributes attrs = new XmlAttributes();
 19 
 20             /* Create an XmlElementAttribute to override the
 21             field that returns Instrument objects. The overridden field
 22             returns Brass objects instead. */
 23             //创建XmlElementAttribute以覆盖返回仪器对象的字段。替代的字段返回黄铜对象。
 24             XmlElementAttribute attr = new XmlElementAttribute();
 25             attr.ElementName = "Brass";
 26             attr.Type = typeof(Brass);
 27 
 28             // 添加元素到集合
 29             attrs.XmlElements.Add(attr);
 30 
 31             // 创建XmlAttributeOverrides
 32             XmlAttributeOverrides attrOverrides = new XmlAttributeOverrides();
 33 
 34             /* Add the type of the class that contains the overridden
 35             member and the XmlAttributes to override it with to the
 36             XmlAttributeOverrides object. */
 37             //将包含重写成员的类的类型以及要用其重写的XmlAttributeOverrides对象的XmlAttributes添加到XmlAttributeOverrides对象。
 38             attrOverrides.Add(typeof(Orchestra), "Instruments", attrs);
 39 
 40             // Create the XmlSerializer using the XmlAttributeOverrides.
 41             XmlSerializer s = new XmlSerializer(typeof(Orchestra), attrOverrides);
 42 
 43             using (TextWriter writer = new StreamWriter(filename)) 
 44             {
 45                 // Create the object that will be serialized.
 46                 Orchestra band = new Orchestra();
 47 
 48                 // Create an object of the derived type.
 49                 Brass i = new Brass();
 50                 i.Name = "Trumpet";
 51                 i.IsValved = true;
 52                 Instrument[] myInstruments = { i };
 53                 band.Instruments = myInstruments;
 54 
 55                 // Serialize the object.
 56                 s.Serialize(writer, band);
 57             }
 58 
 59             
 60         }
 61 
 62         public void DeserializeObject(string filename)
 63         {
 64             XmlAttributeOverrides attrOverrides =
 65                new XmlAttributeOverrides();
 66             XmlAttributes attrs = new XmlAttributes();
 67 
 68             // Create an XmlElementAttribute to override the Instrument.
 69             XmlElementAttribute attr = new XmlElementAttribute();
 70             attr.ElementName = "Brass";
 71             attr.Type = typeof(Brass);
 72 
 73             // Add the XmlElementAttribute to the collection of objects.
 74             attrs.XmlElements.Add(attr);
 75 
 76             attrOverrides.Add(typeof(Orchestra), "Instruments", attrs);
 77 
 78             // Create the XmlSerializer using the XmlAttributeOverrides.
 79             XmlSerializer s =
 80             new XmlSerializer(typeof(Orchestra), attrOverrides);
 81 
 82             FileStream fs = new FileStream(filename, FileMode.Open);
 83             Orchestra band = (Orchestra)s.Deserialize(fs);
 84             Console.WriteLine("Brass:");
 85 
 86             /* The difference between deserializing the overridden
 87             XML document and serializing it is this: To read the derived
 88             object values, you must declare an object of the derived type
 89             (Brass), and cast the Instrument instance to it. */
 90             Brass b;
 91             foreach (Instrument i in band.Instruments)
 92             {
 93                 b = (Brass)i;
 94                 Console.WriteLine(
 95                 b.Name + "\n" +
 96                 b.IsValved);
 97             }
 98         }
 99     }
100 }
序列化反序列化代码
1 <?xml version="1.0" encoding="utf-8"?>
2 <Orchestra xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
3   <Brass>
4     <Name>Trumpet</Name>
5     <IsValved>true</IsValved>
6   </Brass>
7 </Orchestra>
序列化结果

XmlAttributeOverrides类重写默认序列化逻辑具体可见:https://docs.microsoft.com/zh-cn/dotnet/api/system.xml.serialization.xmlattributeoverrides?redirectedfrom=MSDN&view=net-6.0

3.5、将对象序列化为SOAP编码的XML流

将对象序列化为 SOAP 编码的 XML 流具体可见:https://docs.microsoft.com/zh-cn/dotnet/standard/serialization/how-to-serialize-an-object-as-a-soap-encoded-xml-stream

4、JSON序列化&反序列化

4.1、JSON序列化

  JSON序列化目前有两种方式:①使用JsonSerializer类,System.Text.Json 命名空间包含所有入口点和主要类型,System.Text.Json.Serialization 命名空间包含用于高级方案的特性和 API,以及特定于序列化和反序列化的自定义。②使用开源库Newtonsoft.Json。

4.2、使用System.Text.Json序列化&反序列化

   本节演示如何使用 System.Text.Json 命名空间向/从 JavaScript 对象表示法 (JSON) 进行序列化和反序列化。  注意:大多数序列化示例代码将 JsonSerializerOptions.WriteIndented 设置为 true,以 JSON 进行优质打印(包含缩进和空格,以提高可读性)。 对于生产用途,通常对于此设置会接受默认值 false。

 1 using System;
 2 
 3 namespace Demo06_JsonSerializer
 4 {
 5     public class SerializeObject
 6     {
 7         public string Name { get; set; }
 8         public int _Age;
 9         public MyObject MyObjectDate { get; set; }
10         public int Count { get; set; }
11         private bool _sex; 
12         public SerializeObject(string name, int age, bool sex)
13         {
14             this.Name = name;
15             this._Age = age;
16             this._sex = sex;
17             this.MyObjectDate = new MyObject() { CreateTime = DateTime.Now };
18         }
19         public SerializeObject() //序列化的时候必须要无参的构造函数
20         {
21             Console.WriteLine("SerializeObject对象构造函数。");
22         }
23     }
24     public class MyObject
25     {
26         public DateTime CreateTime { get; set; }
27     }
28 }
序列化对象SerializeObject
 1 using System;
 2 using System.IO;
 3 using System.Text.Json;
 4 
 5 namespace Demo06_JsonSerializer
 6 {
 7     internal class Program
 8     {
 9         static void Main(string[] args)
10         {
11             //JSON序列化
12             SerializeObject serializeObject = new SerializeObject("BigBox777", 18, true);
13             using (TextWriter tw = new StreamWriter("JsonSerializer.json"))
14             {
15                 //将 JsonSerializerOptions.WriteIndented 设置为 true,以 JSON 进行优质打印
16                 //(包含缩进和空格,以提高可读性)。 对于生产用途,通常对于此设置会接受
17                 //默认值 false。
18                 JsonSerializerOptions jsonSerializerOptions = new JsonSerializerOptions();
19                 jsonSerializerOptions.WriteIndented = true;
20                 string jsonStr = JsonSerializer.Serialize<SerializeObject>(serializeObject, jsonSerializerOptions);
21                 tw.Write(jsonStr);
22                 Console.WriteLine(jsonStr);
23             }
24 
25             ////JSON反序列化
26             //using (TextReader tr=new StreamReader("JsonSerializer.json"))
27             //{
28             //    SerializeObject serializeObject1 = JsonSerializer.Deserialize<SerializeObject>(tr.ReadToEnd());
29             //}
30 
31             Console.ReadLine();
32         }
33     }
34 }
序列化反序列化代码
1 {
2   "Name": "BigBox777",
3   "MyObjectDate": {
4     "CreateTime": "2021-12-16T09:07:30.2494361+08:00"
5   },
6   "Count": 0
7 }
序列化结果

4.3、使用Newtonsoft.Json序列化&反序列化

   使用Newtonsoft.Json进行序列化&反序列化之前需要安装Newtonsoft.Json开源库,在项目上使用nuget包管理器,搜索 Newtonsoft.Json 进行安装,我这里安装稳定版13.0.1。

 1 using System;
 2 using System.Collections.Generic;
 3 
 4 namespace Demo06_NewtonsoftJson
 5 {
 6     public class WeatherForecastWithPOCOs
 7     {
 8         public DateTimeOffset Date { get; set; }
 9         public int TemperatureCelsius { get; set; }
10         public string Summary { get; set; }
11         public string SummaryField;
12         public IList<DateTimeOffset> DatesAvailable { get; set; }
13         public Dictionary<string, HighLowTemps> TemperatureRanges { get; set; }
14         public string[] SummaryWords { get; set; }
15     }
16 
17     public class HighLowTemps
18     {
19         public int High { get; set; }
20         public int Low { get; set; }
21     }
22 }
序列化对象WeatherForecastWithPOCOs
 1 using Newtonsoft.Json;
 2 using System;
 3 using System.Collections.Generic;
 4 using System.IO;
 5 
 6 namespace Demo06_NewtonsoftJson
 7 {
 8     internal class Program
 9     {
10         static void Main(string[] args)
11         {
12             ////序列化
13             //WeatherForecastWithPOCOs weatherForecastWithPOCOs = new WeatherForecastWithPOCOs()
14             //{
15             //    Date = DateTime.Now,
16             //    TemperatureCelsius = 25,
17             //    Summary = "Hot",
18             //    DatesAvailable = new List<DateTimeOffset>() { DateTimeOffset.Now, DateTimeOffset.Now },
19             //    SummaryWords = new string[] { "Cool", "Windy", "mid" }
20             //};
21             //weatherForecastWithPOCOs.TemperatureRanges = new Dictionary<string, HighLowTemps>();
22             //weatherForecastWithPOCOs.TemperatureRanges.Add("Cold",new HighLowTemps() { High=20,  Low=-10});
23             //weatherForecastWithPOCOs.TemperatureRanges.Add("Hot", new HighLowTemps() { High = 60, Low = 20 });
24             //using (TextWriter tw=new StreamWriter("newtonsoftJson.json"))
25             //{
26             //    string jsonStr = JsonConvert.SerializeObject(weatherForecastWithPOCOs);
27             //    tw.WriteLine(jsonStr);
28             //    Console.WriteLine(jsonStr);
29             //}
30 
31             //反序列化
32             using (TextReader tr = new StreamReader("newtonsoftJson.json"))
33             {
34                 WeatherForecastWithPOCOs weatherForecastWithPOCOs = JsonConvert.DeserializeObject<WeatherForecastWithPOCOs>(tr.ReadToEnd());
35             }
36 
37             Console.ReadLine();
38         }
39     }
40 }
序列化反序列化代码
 1 {
 2   "SummaryField": null,
 3   "Date": "2021-12-16T09:52:05.1358337+08:00",
 4   "TemperatureCelsius": 25,
 5   "Summary": "Hot",
 6   "DatesAvailable": [ "2021-12-16T09:52:05.1397264+08:00", "2021-12-16T09:52:05.1400572+08:00" ],
 7   "TemperatureRanges": {
 8     "Cold": {
 9       "High": 20,
10       "Low": -10
11     },
12     "Hot": {
13       "High": 60,
14       "Low": 20
15     }
16   },
17   "SummaryWords": [ "Cool", "Windy", "mid" ]
18 }
序列化结果

4.4、System.Text.Json和Newtonsoft.Json的一些差异

  ①在反序列化过程中,默认情况下 Newtonsoft.Json 进行不区分大小写的属性名称匹配。 System.Text.Json 默认值区分大小写,这可提供更好的性能,因为它执行精确匹配。若要更改该行为,请将 JsonSerializerOptions.PropertyNameCaseInsensitive 设置为 true。
  ②在序列化过程中,Newtonsoft.Json 对于让字符通过而不进行转义相对宽松。 也就是说,它不会将它们替换为 \uxxxx(其中 xxxx 是字符的码位)。 对字符进行转义时,它会通过在字符前发出 \ 来实现此目的(例如," 会变为 \")。 System.Text.Json 会在默认情况下转义较多字符,以对跨站点脚本 (XSS) 或信息泄露攻击提供深度防御保护,并使用六字符序列执行此操作。 System.Text.Json 会在默认情况下转义所有非 ASCII 字符,因此如果在 Newtonsoft.Json 中使用 StringEscapeHandling.EscapeNonAscii,则无需执行任何操作。 System.Text.Json 在默认情况下还会转义 HTML 敏感字符。
  ③在反序列化过程中,Newtonsoft.Json 在默认情况下会忽略 JSON 中的注释。 System.Text.Json 默认值是对注释引发异常,因为 RFC 8259 规范不包含它们。
  ④在反序列化过程中,默认情况下 Newtonsoft.Json 会忽略尾随逗号。 它还会忽略多个尾随逗号(例如 [{"Color":"Red"},{"Color":"Green"},,])。 System.Text.Json 默认值是对尾随逗号引发异常,因为 RFC 8259 规范不允许使用它们。默认情况下,JSON 中不允许使用注释和尾随逗号。 若要在 JSON 中允许注释,请将 JsonSerializerOptions.ReadCommentHandling 属性设置为 JsonCommentHandling.Skip。 若要允许尾随逗号,请将 JsonSerializerOptions.AllowTrailingCommas 属性设置为 true。

  更多请参考文章:https://docs.microsoft.com/zh-cn/dotnet/standard/serialization/system-text-json-migrate-from-newtonsoft-how-to?pivots=dotnet-6-0

5、参考

  .NET 中的序列化 & 反序列化(雪飞鸿博客)  https://www.cnblogs.com/Cwj-XFH/p/10330671.html
  Json的序列化与反序列化(CesarLai博客) https://www.cnblogs.com/cesarlai/p/7538437.html
  C#对象序列化与反序列化(KyrieYang博客) https://www.cnblogs.com/yzenet/p/3622833.html
  C#编程总结(一)序列化(停留的风博客) https://www.cnblogs.com/yank/p/3198082.html
  .NET 中的序列化(微软docs) https://docs.microsoft.com/zh-cn/dotnet/standard/serialization/

原文地址:https://www.cnblogs.com/bigbox777/p/14414500.html