本文概述了序列化和反序列化支持哪些类型。
序列化为 JSON 对象的类型
以下类型序列化为 JSON 对象:
- 类*
- 结构
- 接口
- 记录和结构记录
* 实现 IEnumerable<T> 序列化为 JSON 数组的非字典类型。 实现 IEnumerable<T>的字典类型将序列化为 JSON 对象。
以下代码片段显示了简单结构的序列化。
public static void Main()
{
var coordinates = new Coords(1.0, 2.0);
string json = JsonSerializer.Serialize(coordinates);
Console.WriteLine(json);
// Output:
// {"X":1,"Y":2}
}
public readonly struct Coords
{
public Coords(double x, double y)
{
X = x;
Y = y;
}
public double X { get; }
public double Y { get; }
}
序列化为 JSON 数组的类型
.NET 集合类型序列化为 JSON 数组。 如果 System.Text.Json.JsonSerializer 支持用于序列化的集合类型:
- 派生自 IEnumerable 或 IAsyncEnumerable<T>。
- 包含可序列化的元素。
序列化程序调用 GetEnumerator() 方法并写入元素。
反序列化更为复杂,某些集合类型不支持。
以下部分按命名空间进行组织,并显示序列化和反序列化支持的类型。
- System.Array 命名空间
- System.Collections 命名空间
- System.Collections.Generic 命名空间
- System.Collections.Immutable 命名空间
- System.Collections.Specialized 命名空间
- System.Collections.Concurrent 命名空间
- System.Collections.ObjectModel 命名空间
- 自定义集合
System.Array 命名空间
| 类型 | 序列化 | 反序列化 |
|---|---|---|
| 单维数组* | ✔️ | ✔️ |
| 多维数组 | ❌ | ❌ |
| Jagged 数组 | ✔️ | ✔️ |
*
byte[] 作为 base64 字符串(而不是 JSON 数组)进行特殊处理并序列化。
System.Collections 命名空间
| 类型 | 序列化 | 反序列化 |
|---|---|---|
| ArrayList | ✔️ | ✔️ |
| BitArray | ✔️ | ❌ |
| DictionaryEntry | ✔️ | ✔️ |
| Hashtable | ✔️ | ✔️ |
| ICollection | ✔️ | ✔️ |
| IDictionary | ✔️ | ✔️ |
| IEnumerable | ✔️ | ✔️ |
| IList | ✔️ | ✔️ |
| Queue | ✔️ | ✔️ |
| SortedList | ✔️ | ✔️ |
| Stack * | ✔️ | ✔️ |
* 请参阅 支持往返 Stack 类型。
System.Collections.Generic 命名空间
| 类型 | 序列化 | 反序列化 |
|---|---|---|
| Dictionary<TKey,TValue> * | ✔️ | ✔️ |
| HashSet<T> | ✔️ | ✔️ |
| IAsyncEnumerable<T> † | ✔️ | ✔️ |
| ICollection<T> | ✔️ | ✔️ |
| IDictionary<TKey,TValue> * | ✔️ | ✔️ |
| IEnumerable<T> | ✔️ | ✔️ |
| IList<T> | ✔️ | ✔️ |
| IReadOnlyCollection<T> | ✔️ | ✔️ |
| IReadOnlyDictionary<TKey,TValue> * | ✔️ | ✔️ |
| IReadOnlyList<T> | ✔️ | ✔️ |
| ISet<T> | ✔️ | ✔️ |
| KeyValuePair<TKey,TValue> | ✔️ | ✔️ |
| LinkedList<T> | ✔️ | ✔️ |
| LinkedListNode<T> | ✔️ | ❌ |
| List<T> | ✔️ | ✔️ |
| Queue<T> | ✔️ | ✔️ |
| SortedDictionary<TKey,TValue> * | ✔️ | ✔️ |
| SortedList<TKey,TValue> * | ✔️ | ✔️ |
| SortedSet<T> | ✔️ | ✔️ |
| Stack<T> • | ✔️ | ✔️ |
* 请参阅 支持的密钥类型。
†请参阅有关 IAsyncEnumerable<T>的以下部分。
• 请参阅 支持往返 Stack 类型。
IAsyncEnumerable<T>
以下示例使用流作为任何异步数据源的表示形式。 源可以是本地计算机上的文件,也可以是数据库查询或 Web 服务 API 调用的结果。
流序列化
System.Text.Json 支持将 IAsyncEnumerable<T> 值序列化为 JSON 数组,如以下示例所示:
using System.Text.Json;
namespace IAsyncEnumerableSerialize;
public class Program
{
public static async Task Main()
{
using Stream stream = Console.OpenStandardOutput();
var data = new { Data = PrintNumbers(3) };
await JsonSerializer.SerializeAsync(stream, data);
}
static async IAsyncEnumerable<int> PrintNumbers(int n)
{
for (int i = 0; i < n; i++)
{
await Task.Delay(1000);
yield return i;
}
}
}
// output:
// {"Data":[0,1,2]}
IAsyncEnumerable<T> 值仅受异步序列化方法(如 JsonSerializer.SerializeAsync)的支持。
流反序列化
DeserializeAsyncEnumerable 方法支持流反序列化,如以下示例所示:
using System.Text;
using System.Text.Json;
namespace IAsyncEnumerableDeserialize;
public class Program
{
public static async Task Main()
{
using var stream = new MemoryStream(Encoding.UTF8.GetBytes("[0,1,2,3,4]"));
await foreach (int item in JsonSerializer.DeserializeAsyncEnumerable<int>(stream))
{
Console.WriteLine(item);
}
}
}
// output:
//0
//1
//2
//3
//4
DeserializeAsyncEnumerable 方法仅支持从根级 JSON 数组进行读取。
DeserializeAsync 方法支持 IAsyncEnumerable<T>,但其签名不允许流式传输。 它以单个值的形式返回最终结果,如以下示例所示。
using System.Text;
using System.Text.Json;
namespace IAsyncEnumerableDeserializeNonStreaming;
public class MyPoco
{
public IAsyncEnumerable<int>? Data { get; set; }
}
public class Program
{
public static async Task Main()
{
using var stream = new MemoryStream(Encoding.UTF8.GetBytes(@"{""Data"":[0,1,2,3,4]}"));
MyPoco? result = await JsonSerializer.DeserializeAsync<MyPoco>(stream)!;
await foreach (int item in result!.Data!)
{
Console.WriteLine(item);
}
}
}
// output:
//0
//1
//2
//3
//4
在此示例中,反序列化程序在返回反序列化对象之前缓冲内存中的所有 IAsyncEnumerable<T> 内容。 此行为是必需的,因为反序列化程序需要在返回结果之前读取整个 JSON 有效负载。
System.Collections.Immutable 命名空间
| 类型 | 序列化 | 反序列化 |
|---|---|---|
| IImmutableDictionary<TKey,TValue> † | ✔️ | ✔️ |
| IImmutableList<T> | ✔️ | ✔️ |
| IImmutableQueue<T> | ✔️ | ✔️ |
| IImmutableSet<T> | ✔️ | ✔️ |
| IImmutableStack<T> * | ✔️ | ✔️ |
| ImmutableArray<T> | ✔️ | ✔️ |
| ImmutableDictionary<TKey,TValue> † | ✔️ | ✔️ |
| ImmutableHashSet<T> | ✔️ | ✔️ |
| ImmutableQueue<T> | ✔️ | ✔️ |
| ImmutableSortedDictionary<TKey,TValue> † | ✔️ | ✔️ |
| ImmutableSortedSet<T> | ✔️ | ✔️ |
| ImmutableStack<T> * | ✔️ | ✔️ |
* 请参阅 支持往返 Stack 类型。
†请参阅 支持的密钥类型。
System.Collections.Specialized 命名空间
| 类型 | 序列化 | 反序列化 |
|---|---|---|
| BitVector32 | ✔️ | ❌* |
| HybridDictionary | ✔️ | ✔️ |
| IOrderedDictionary | ✔️ | ❌ |
| ListDictionary | ✔️ | ✔️ |
| NameValueCollection | ✔️ | ❌ |
| StringCollection | ✔️ | ❌ |
| StringDictionary | ✔️ | ❌ |
* 反序列化 BitVector32 时,将跳过 Data 属性,因为它没有公共资源库。 不会引发异常。
System.Collections.Concurrent 命名空间
| 类型 | 序列化 | 反序列化 |
|---|---|---|
| BlockingCollection<T> | ✔️ | ❌ |
| ConcurrentBag<T> | ✔️ | ❌ |
| ConcurrentDictionary<TKey,TValue> † | ✔️ | ✔️ |
| ConcurrentQueue<T> | ✔️ | ✔️ |
| ConcurrentStack<T> * | ✔️ | ✔️ |
* 请参阅 支持往返 Stack 类型。
†请参阅 支持的密钥类型。
System.Collections.ObjectModel 命名空间
| 类型 | 序列化 | 反序列化 |
|---|---|---|
| Collection<T> | ✔️ | ✔️ |
| KeyedCollection<字符串 TValue> * | ✔️ | ❌ |
| ObservableCollection<T> | ✔️ | ✔️ |
| ReadOnlyCollection<T> | ✔️ | ❌ |
| ReadOnlyDictionary<TKey,TValue> | ✔️ | ❌ |
| ReadOnlyObservableCollection<T> | ✔️ | ❌ |
* 不支持非string 键。
自定义集合
任何不在上述命名空间中的集合类型都被视为自定义集合。 此类类型包括由 ASP.NET Core 定义的用户定义的类型和类型。 例如,Microsoft.Extensions.Primitives 在此组中。
所有自定义集合(从 IEnumerable派生的所有内容)都支持序列化,只要支持它们的元素类型。
反序列化支持
如果反序列化,则支持自定义集合:
不是接口或抽象。
具有无参数构造函数。
包含 JsonSerializer支持的元素类型。
实现或继承以下一个或多个接口或类:
- ConcurrentQueue<T>
- ConcurrentStack<T> *
- ICollection<T>
- IDictionary
- IDictionary<TKey,TValue> †
- IList
- IList<T>
- Queue
- Queue<T>
- Stack *
- Stack<T> *
* 请参阅 支持往返
Stack类型。†请参阅 支持的密钥类型。
已知问题
以下自定义集合存在已知问题:
- ExpandoObject:请参阅 dotnet/runtime#29690。
- DynamicObject:请参阅 dotnet/runtime#1808。
- DataTable:请参阅 dotnet/docs#21366。
- Microsoft.AspNetCore.Http.FormFile:请参阅 dotnet/runtime#1559。
- Microsoft.AspNetCore.Http.IFormCollection:请参阅 dotnet/runtime#1559。
有关已知问题的详细信息,请参阅
支持的密钥类型
当用作 Dictionary 和 SortedList 类型的键时,以下类型具有内置支持:
BooleanByteDateTimeDateTimeOffsetDecimalDoubleEnumGuidInt16Int32Int64-
Object(仅在序列化时,如果运行时类型是此列表中的支持类型之一)。 SByteSingleString- TimeSpan
UInt16UInt32UInt64- Uri
- Version
此外,JsonConverter<T>.WriteAsPropertyName(Utf8JsonWriter, T, JsonSerializerOptions) 和 JsonConverter<T>.ReadAsPropertyName(Utf8JsonReader, Type, JsonSerializerOptions) 方法允许为任何类型的选择添加字典键支持。
不支持的类型
序列化不支持以下类型:
- System.Type 和 System.Reflection.MemberInfo
- 一般情况下,ReadOnlySpan<T>、Span<T>和 ref 结构
- 委托类型
- IntPtr 和 UIntPtr
System.Data 命名空间
DataSet 命名空间中没有 DataTable、System.Data和相关类型的内置转换器。 从不受信任的输入反序列化这些类型是不安全的,如 安全指南中所述。 但是,可以编写自定义转换器来支持这些类型。 有关序列化和反序列化 DataTable的示例自定义转换器代码,请参阅 RoundtripDataTable.cs。