Поделиться через


Поддерживаемые типы в 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 * ✔️ ✔️

* Дополнительные сведения отипах поддержки см. в разделе поддержки.

Пространство имен 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>

В следующих примерах потоки используются в качестве представления любого асинхронного источника данных. Источник может быть файлами на локальном компьютере или результатом вызова API базы данных или 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> * ✔️ ✔️

* Дополнительные сведения отипах поддержки см. в разделе поддержки.

† См. поддерживаемые типы ключей.

System.Collections.Специализированное пространство имен

Тип Сериализация Десериализация
BitVector32 ✔️ ❌*
HybridDictionary ✔️ ✔️
IOrderedDictionary ✔️
ListDictionary ✔️ ✔️
NameValueCollection ✔️
StringCollection ✔️
StringDictionary ✔️

* При десериализации BitVector32 свойство Data пропускается, так как оно не имеет общедоступного набора. Исключение не возникает.

Пространство имен System.Collections.Concurrent

Тип Сериализация Десериализация
BlockingCollection<T> ✔️
ConcurrentBag<T> ✔️
ConcurrentDictionary<TKey,TValue> ✔️ ✔️
ConcurrentQueue<T> ✔️ ✔️
ConcurrentStack<T> * ✔️ ✔️

* Дополнительные сведения отипах поддержки см. в разделе поддержки.

† См. поддерживаемые типы ключей.

Пространство имен System.Collections.ObjectModel

Тип Сериализация Десериализация
Collection<T> ✔️ ✔️
строка<KeyedCollection, TValue> * ✔️
ObservableCollection<T> ✔️ ✔️
ReadOnlyCollection<T> ✔️
ReadOnlyDictionary<TKey,TValue> ✔️
ReadOnlyObservableCollection<T> ✔️

* Ключи, отличные отstring, не поддерживаются.

Пользовательские коллекции

Любой тип коллекции, который не находится в одном из предыдущих пространств имен, считается пользовательской коллекцией. Такие типы включают определяемые пользователем типы и типы, определенные ASP.NET Core. Например, Microsoft.Extensions.Primitives находится в этой группе.

Все пользовательские коллекции (все, производные от IEnumerable) поддерживаются для сериализации, если поддерживаются их типы элементов.

Поддержка десериализации

Пользовательская коллекция поддерживается для десериализации, если она:

Известные проблемы

Существуют известные проблемы со следующими настраиваемыми коллекциями:

Дополнительные сведения об известных проблемах см. в открытых проблемах в System.Text.Json.

Поддерживаемые типы ключей

При использовании в качестве ключей типов Dictionary и SortedList следующие типы имеют встроенную поддержку:

  • 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

Встроенные преобразователи для DataSet, DataTableи связанных типов в пространстве имен System.Data отсутствуют. Десериализация этих типов из ненадежных входных данных не является безопасной, как описано в руководстве по безопасности. Однако можно написать пользовательский преобразователь для поддержки этих типов. Пример пользовательского кода преобразователя, который сериализует и десериализирует DataTable, см. RoundtripDataTable.cs.

См. также