JSON serializatoin
- Overview
- System.Text.Json,强调高性能以及低内存占用
- 内置UTF-8支持
- 提供驻内存的文档对象模型,以支持对元素的随机读写
- VB支持受限
-
How to get the library
- 内置于.NET Core 3.0及以后的版本,之前的版本要按照System.Text.Json料包
- source generation feature内置越.NET 6及以后
-
Run-time reflection vs. compile-time source generation
- 默认情况下,System.Text.Json使用勘察功能来获取元素据,以在序列化,反序列化中对应到对象的辖属
- 使用source generatoin特性可以提供性能,减少内存使用,促进装配件剪裁
-
Security information
-
Thread safety
- (过)
- System.Text.Json,强调高性能以及低内存占用
- Reflection vs. source generation
-
Overview
- 基于勘察的实现具有更高的灵活性
- 支持非公开访问符
- 支持init-only辖属
- 支持所有的序列化自定义
- 基于勘察的实现具有更高的灵活性
-
- How to serialize and deserialize JSON
-
Code samples(过)
-
Namespaces
- System.Text.Json
- 不支持System.Runtime.Serialization中的属性
- 不支持System.SerializableAttribute和ISerializable
- System.Text.Json.Serialization,包含属性以及用于高级场景的API
- System.Text.Json
-
How to write .NET objects as JSON (serialize)
- 使用JsonSerializer.Serialize
- .NET 7支持DateOnly和TimeOnly类型的序列化
-
Serialization example(过)
-
Serialize to UTF-8
- 序列化成 UTF-8字节流比序列化成string(UTF-16格式)快5-10%。
- 例子
byte[] jsonUtf8Bytes =JsonSerializer.SerializeToUtf8Bytes(weatherForecast);
-
Serialization behavior
- 一些默认设置
- 默认所有公开的辖属都会被序列化,可以指出需要忽略的
- 默认的录编器转义所有的非ASCII字符、ASCII范围内HTML敏感的字符、以及RFC8259所要求的
- 默认情况下,JSON会被最小化,可以要求漂亮打印
- 默认情况下,JSON名字的大小写与.NET名字匹配,可以自定义名字大小写
- 默认情况下,会检查循环引用并对其抛出异常,可以保留并处理循环引用
- 默认情况下,会忽略域属,可以加入域属
- ASP.NET Core中默认设置有所不同,参考https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/configure-options#web-defaults-for-jsonserializeroptions
- 支持的类型包括
- 可以在.NET和JS直接映射的元初类型,比如数值类型、字符串以及布尔类型
- 用户定义的POCO:https://learn.microsoft.com/en-us/dotnet/standard/glossary#poco
- 一维数组或者参差数组(
T[][]
) - 下列名字空间中的合集和字典
- System.Collections
- System.Collections.Generic
- System.Collections.Immutable
- System.Collections.Concurrent
- System.Collections.Specialized
- System.Collections.ObjectModel
- 更多参考https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/supported-collection-types
- 一些默认设置
-
How to read JSON as .NET objects (deserialize)
- (停于此)
-
- Migrate from Newtonsoft.Json
- System.Text.Json侧重新能,以及标准的遵从性
-
Table of differences between Newtonsoft.Json and System.Text.Json
- 看起来Newtonsoft.Json具有更多特性
Serialization in .NET
序列化是指将内存中对象的状态,转化为能够持久存储或传输的格式。
.NET提供了以下的序列化技术:
- JSON序列化,提供对公开辖属的序列化,但是不保证类型如实性(fidelity)。
- 二进制序列化,支持类型的如实性,也就是能够完整保存对象的状态
- XML以及SOAP序列化,支持公开的辖属,以及那些不需要保持类型如实性的字段。
XML序列化
XML and SOAP serialization
XML序列化支持将对象的公开字段和辖属、方法的参数和返回值等转为XML数据流,过程可以依照XSD进行。
XML序列化支持SOAP协议格式。
主要的主类是XmlSerializer。
XML serialization
XML序列化不包含类型信息。
XML serialization does not convert methods, indexers, private fields, or read-only properties (except read-only collections). To serialize all an object’s fields and properties, both public and private, use the DataContractSerializer instead of XML serialization.
此序列化过程会用到XmlSerializer的Serialize和Deserialize方法。
XmlSerializer需要创建C#源码,并将其编译成.dll文件。 Sgen可以服务于此目的。
XmlSerializer生成的XML数据流符合W3C的XSD标准,具体是"XML Schema Part 2: Datatypes.“部分。
除了编程语言结构之外,可以使用XmlElement或XmlAttribute对象嵌入XML。所以,可以自行创建主类来对应XML结构,也可以使用工具从XSD生成主类。参考https://learn.microsoft.com/en-us/dotnet/standard/data/xml/。
可以用属性来控制XmlSerializer生成的XML数据流。参考https://learn.microsoft.com/en-us/dotnet/standard/serialization/controlling-xml-serialization-using-attributes。对于属性列表,可以参考https://learn.microsoft.com/en-us/dotnet/standard/serialization/attributes-that-control-xml-serialization。
XmlSerializer可以生成SOAP录编的XML数据流,符合W3C的SOAP 1.1标准的第五节。参考 https://learn.microsoft.com/en-us/dotnet/standard/serialization/how-to-serialize-an-object-as-a-soap-encoded-xml-stream,以及https://learn.microsoft.com/en-us/dotnet/standard/serialization/attributes-that-control-encoded-soap-serialization。
可以通过XML Web service file (.asmx)来控制SOAP消息。更多参考https://learn.microsoft.com/en-us/dotnet/standard/serialization/xml-serialization-with-xml-web-services,以及https://learn.microsoft.com/en-us/previous-versions/dotnet/netframework-4.0/dkwy2d72(v=vs.100)。
Security Considerations for XmlSerializer Applications
使用XmlSerializer的注意事项:
- XmlSerializer在TEMP环境变量所指的目录创建.cs文件并编译之
这些.cs文件可以提前用SGen.exe生成 不要随便分享这些TEMP目录
- 如果数据流太长,那么XmlSerializer可能会耗尽内存
- XmlSerializer会执行反序列化出来的代码,可能存在风险
- 不要序列话敏感数据
Serialization of a Simple Class
对于下面这个主类:
public class OrderForm
{
public DateTime OrderDate;
}
其XML序列化形式可能是:
<OrderForm>
<OrderDate>12/12/01</OrderDate>
</OrderForm>
更多例子参考:https://learn.microsoft.com/en-us/dotnet/standard/serialization/examples-of-xml-serialization
Items That Can Be Serialized
下列条目可以被XmlSerializer序列化:
- 公开的读写辖属,以及公开的主类的字段
- 实现了ICollection或IEnumerable的主类
- Only collections are serialized, not public properties.
- XmlElement对象
- XmlNode对象
- DataSet对象
参考https://learn.microsoft.com/en-us/dotnet/standard/serialization/how-to-serialize-an-object以及https://learn.microsoft.com/en-us/dotnet/standard/serialization/how-to-deserialize-an-object
Advantages of Using XML Serialization
XmlSerializer可以使你:
- 指定一个字段或者辖属是否要录编成一个XML的属性或元素
- 指定XML的命名空间
- 指定跟字段或辖属不兼容的元素或者属性的名字
XML数据流只需要遵循XSD,所以不会特别受程序语言限制
XML Serialization Considerations
- Sgen.exe可以生成高效的装配件
- 序列化后的数据只存有数据本身,类型信息会丢失
- 只有公开的字段和辖属会被序列化,对于非公开的,需要使用https://learn.microsoft.com/en-us/dotnet/api/system.runtime.serialization.datacontractserializer
- 一个主类必须有无参构造器
- 方法补能被序列化
- XmlSerializer 可以处理实现了IEnumerable 或ICollection的主类
- 具体要求看文档中的说明
XSD Data Type Mapping
https://www.w3.org/TR/xmlschema-2/中允许XSD中有简单的数据类型。大部分数据类型在.NET中有对应的类型,少部分没有,比如NMTOKEN数据类型。如果你使用https://learn.microsoft.com/en-us/dotnet/standard/serialization/xml-schema-definition-tool-xsd-exe从XSD中生成主类的时候,会生成下面的代码:
[XmlElement(DataType = "NMTOKEN")]
public string MyToken;
下面的属性主类均有DataType辖属:
- SoapAttributeAttribute
- SoapElementAttribute
- XmlArrayItemAttribute
- XmlAttributeAttribute
- XmlElementAttribute
- XmlRootAttribute
XML Serializer Generator Tool (Sgen.exe)
用于预先生成XmlSerializer所需的源码文件。
需要在VS提供的shell中运行sgen。
例子:sgen Data.dll
会创建一个名为Data.XamlSerializers.dll的装配件,包含Data.dll中的相关类型。
注意点
- 只适用于可以手动提前生成,不适用于运行时生成
- 如果需要序列化的类型包含在装配件MyType.dll,那么生成的序列化用的主类会在MyType.XmlSerializers.dll中。
XML Schema Definition Tool (Xsd.exe)
用于从XDR、XML以及XSD文件中生成序列化用的主类。
通常可以在C:\Program Files (x86)\Microsoft SDKs\Windows\{version}\bin\NETFX {version} Tools\
获取。
xsd
注意点:
xsd.exe可以执行以下操作:
- XDR to XSD
- XML to XSD
- XSD to DataSet
- XSD to Classes
- Classes to XSD
所以可以从XML推出XSD,再从XSD生成classes。 命令行指定XSD的话,要指定全部所有的XSD,以避免引用找不到。
可用的措辞如下:
xsd file.xdr [-outputdir:directory][/parameters:file.xml]
xsd file.xml [-outputdir:directory] [/parameters:file.xml]
xsd file.xsd {/classes | /dataset} [/element:element]
[/enableLinqDataSet] [/language:language]
[/namespace:namespace] [-outputdir:directory] [URI:uri]
[/parameters:file.xml]
xsd {file.dll | file.exe} [-outputdir:directory] [/type:typename [...]][/parameters:file.xml]
可以用/parameters
来指定一个内含配置的文件。
Control XML serialization using attributes
默认情况下,XML元素的名字是根据主类或者成员来的。如下所示:
public class Book
{
public string ISBN;
}
// When an instance of the Book class is serialized, it might
// produce this XML:
// <ISBN>1234567890</ISBN>.
可以通过设置属性[XmlElement(ElementName = "TaxRate")]
的方式给XML元素起新的名字。
Controlling Array Serialization
XmlArrayAttribute和 XmlArrayItemAttribute用来控制数组的序列化。
比如:
public class Group {
[XmlArray("TeamMembers")]
public Employee[] Employees;
}
public class Group {
[XmlArrayItem("MemberName")]
public Employee[] Employees;
}
Serializing Derived Classes
XmlArrayItemAttribute可以允许序列化派生主类。可以在属性上同时指定基础主类和派生主类:
public class Group {
[XmlArrayItem(Type = typeof(Employee)),
XmlArrayItem(Type = typeof(Manager))]
public Employee[] Employees;
}
Serializing an Array as a Sequence of Elements
也可以直接将在数组上以扁平的方式序列化:
public class Group {
[XmlElement]
public Employee[] Employees;
}
XSD产生的代码对XML项列的处理上有所不同。
Serializing an ArrayList
可以直接序列化ArrayList:
public class Group {
[XmlElement(Type = typeof(Employee)),
XmlElement(Type = typeof(Manager))]
public ArrayList Info;
}
Controlling Serialization of Classes Using XmlRootAttribute and XmlTypeAttribute
XmlRootAttribute只可应用在顶部的元素,XmlTypeAttribute则可以用于顶部元素之外的元素。
例子:
[XmlRoot("NewGroupName")]
[XmlType("NewTypeName")]
public class Group {
public Employee[] Employees;
}
Preventing Serialization with the XmlIgnoreAttribute
可以使用XmlIgnoreAttribute来在序列化过程中忽略一些元素。
Attributes That Control XML Serialization
XmlSerializer理解以下属性:
- XmlAnyAttributeAttribute,作用对象是XmlAttribue对象项列
- XmlAnyElementAttribute,作用对象是XmlElement对象项列
- XmlArrayAttribute,作用对象是是复合对象项列
- XmlArrayItemAttribute,作用对象是复合对象项列
- XmlAttributeAttribute
- XmlChoiceIdentifierAttribute
- XmlElementAttribute
- XmlEnumAttribute
- XmlIgnoreAttribute
- XmlIncludeAttribute,用于Web Services Description Language
- XmlRootAttribute
- XmlTextAttribute
- XmlTypeAttribute
这些类型都在System.Xml.Serialization命名空间下。 除了以上列出的,还可以使用DefaultValueAttribute。
How-tos
How to deserialize an object using XmlSerializer
反序列化的时候,先确定传输格式(是数据流还是文件对象)然后调用Serialize或者Deserialize方法。
// Construct an instance of the XmlSerializer with the type
// of object that is being deserialized.
var mySerializer = new XmlSerializer(typeof(MySerializableClass));
// To read the file, create a FileStream.
using var myFileStream = new FileStream("myFileName.xml", FileMode.Open);
// Call the Deserialize method and cast to the object type.
var myObject = (MySerializableClass)mySerializer.Deserialize(myFileStream);
How to: Use the XML Schema Definition Tool to Generate Classes and XML Schema Documents
Xsd.exe可以用于从XML廓图生成主类,也可以从主类生成XML廓图。
Xsd.exe可以从以下位置获取C:\Program Files (x86)\Microsoft SDKs\Windows\{version}\bin\NETFX {version} Tools\
。
其他参考
- https://www.c-sharpcorner.com/article/convert-xml-files-data-to-list-of-object2/
- https://stackoverflow.com/questions/9336851/how-to-map-xml-file-content-to-c-sharp-objects
(此处是底部)