System.Text.Json 中支持的集合类型
本文概述了可进行序列化和反序列化的集合的概述。 System.Text.Json.JsonSerializer 支持将集合类型进行序列化,只要集合类型满足以下条件:
- 派生自 IEnumerable 或 IAsyncEnumerable<T>
- 包含可序列化的元素。
序列化程序调用 GetEnumerator() 方法并写入元素。
反序列化更为复杂,并且某些集合类型不支持反序列化。
以下各节按命名空间划分,并显示序列化和反序列化支持的类型。
System.Array 命名空间
类型 | 序列化 | 反序列化 |
---|---|---|
一维数组 | ✔ | ✔ |
多维数组 | ❌ | ❌ |
交错数组 | ✔ | ✔ |
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<string, 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。
有关已知问题详细信息,请参阅 System.Text.Json 中的未解决问题。
支持的密钥类型
Dictionary
和 SortedList
的密钥支持的类型包括:
Boolean
Byte
DateTime
DateTimeOffset
Decimal
Double
Enum
Guid
Int16
Int32
Int64
Object
(仅针对序列化,并且运行时类型是此列表中的支持类型之一。)SByte
Single
String
UInt16
UInt32
UInt64
System.Data 命名空间
System.Data 命名空间中没有用于 DataSet、DataTable 和相关类型的内置转换器。 从不受信任的输入中反序列化这些类型不安全,如安全指南中所述。 但是,可以编写自定义转换器来支持这些类型。 有关序列化并反序列化 DataTable
的示例自定义转换器代码,请参阅 RoundtripDataTable.cs。
另请参阅
反馈
https://aka.ms/ContentUserFeedback。
即将发布:在整个 2024 年,我们将逐步淘汰作为内容反馈机制的“GitHub 问题”,并将其取代为新的反馈系统。 有关详细信息,请参阅:提交和查看相关反馈