System.Text.Json 中支持的类型

本文概述了序列化和反序列化支持哪些类型。

序列化为 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 支持用于序列化的集合类型:

序列化程序调用 GetEnumerator() 方法并写入元素。

反序列化更为复杂,某些集合类型不支持。

以下部分按命名空间进行组织,并显示序列化和反序列化支持的类型。

System.Array 命名空间

类型 序列化 反序列化
单维数组 ✔️ ✔️
多维数组
Jagged 数组 ✔️ ✔️

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派生的所有内容)都支持序列化,只要支持它们的元素类型。

反序列化支持

如果反序列化,则支持自定义集合:

已知问题

以下自定义集合存在已知问题:

有关已知问题的详细信息,请参阅 打开的问题。

支持的密钥类型

当用作 DictionarySortedList 类型的键时,以下类型具有内置支持:

  • Boolean
  • Byte
  • DateTime
  • DateTimeOffset
  • Decimal
  • Double
  • Enum
  • Guid
  • Int16
  • Int32
  • Int64
  • Object(仅在序列化时,如果运行时类型是此列表中的支持类型之一)。
  • SByte
  • Single
  • String
  • TimeSpan
  • UInt16
  • UInt32
  • UInt64
  • Uri
  • Version

此外,JsonConverter<T>.WriteAsPropertyName(Utf8JsonWriter, T, JsonSerializerOptions)JsonConverter<T>.ReadAsPropertyName(Utf8JsonReader, Type, JsonSerializerOptions) 方法允许为任何类型的选择添加字典键支持。

不支持的类型

序列化不支持以下类型:

System.Data 命名空间

System.Data 命名空间中没有 DataSetDataTable和相关类型的内置转换器。 从不受信任的输入反序列化这些类型是不安全的,如 安全指南中所述。 但是,可以编写自定义转换器来支持这些类型。 有关序列化和反序列化 DataTable的示例自定义转换器代码,请参阅 RoundtripDataTable.cs

另请参阅