Serialization in .NET阅读笔记。

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

      • (过)
  • 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
    • 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

    • 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

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\

其他参考

(此处是底部)