Share via


Unterstützte Sammlungstypen in System.Text.Json

Dieser Artikel bietet eine Übersicht darüber, welche Sammlungen für die Serialisierung und Deserialisierung unterstützt werden. System.Text.Json.JsonSerializer unterstützt einen Sammlungstyp für die Serialisierung, wenn er:

Das Serialisierungsmodul ruft die Methode GetEnumerator() auf und schreibt die Elemente.

Die Deserialisierung ist komplizierter und wird für bestimmte Sammlungstypen nicht unterstützt.

Die folgenden Abschnitte sind nach Namespace sortiert und zeigen, welche Typen für die Serialisierung und Deserialisierung unterstützt werden.

System.Array-Namespace

type Serialisierung Deserialisierung
Eindimensionale Arrays ✔️ ✔️
Mehrdimensionale Arrays
Jagged Arrays ✔️ ✔️

System.Collections-Namespace

type Serialisierung Deserialisierung
ArrayList ✔️ ✔️
BitArray ✔️
DictionaryEntry ✔️ ✔️
Hashtable ✔️ ✔️
ICollection ✔️ ✔️
IDictionary ✔️ ✔️
IEnumerable ✔️ ✔️
IList ✔️ ✔️
Queue ✔️ ✔️
SortedList ✔️ ✔️
Stack * ✔️ ✔️

* Siehe Supportroundtrip für Stack-Typen.

System.Collections.Generic-Namespace

type Serialisierung Deserialisierung
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> ✔️ ✔️

* Siehe Unterstützte Schlüsseltypen

† Siehe den folgenden Abschnitt unter IAsyncEnumerable<T>.

‡ Siehe Supportroundtrip für Stack-Typen.

IAsyncEnumerable<T>

In den folgenden Beispielen werden Streams als Darstellung einer beliebigen asynchronen Datenquelle verwendet. Die Quelle können Dateien auf einem lokalen Computer sowie die Ergebnisse einer Datenbankabfrage oder eines Webdienst-API-Aufrufs sein.

Streamserialisierung

System.Text.Json unterstützt die Serialisierung von IAsyncEnumerable<T>-Werten als JSON-Arrays. Dies wird im folgenden Beispiel gezeigt:

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>-Werte werden nur von asynchronen Serialisierungsmethoden wie JsonSerializer.SerializeAsync unterstützt.

Streamdeserialisierung

Die DeserializeAsyncEnumerable-Methode unterstützt die Streamingdeserialisierung, wie im folgenden Beispiel gezeigt:

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

Die DeserializeAsyncEnumerable-Methode unterstützt nur das Lesen aus JSON-Arrays auf Stammebene.

Die DeserializeAsync-Methode unterstützt IAsyncEnumerable<T>, ihre Signatur lässt jedoch kein Streaming zu. Wie im folgenden Beispiel gezeigt, gibt sie das endgültige Ergebnis als einzelner Wert zurück.

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

In diesem Beispiel puffert der Deserialisierer alle IAsyncEnumerable<T>-Inhalte im Arbeitsspeicher, bevor das deserialisierte Objekt zurückgegeben wird. Dieses Verhalten ist erforderlich, weil der Deserialisierer die gesamten JSON-Nutzdaten lesen muss, bevor ein Ergebnis zurückgegeben wird.

System.Collections.Immutable-Namespace

type Serialisierung Deserialisierung
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> * ✔️ ✔️

* Siehe Supportroundtrip für Stack-Typen.

† Siehe Unterstützte Schlüsseltypen.

System.Collections.Specialized-Namespace

type Serialisierung Deserialisierung
BitVector32 ✔️ ❌*
HybridDictionary ✔️ ✔️
IOrderedDictionary ✔️
ListDictionary ✔️ ✔️
NameValueCollection ✔️
StringCollection ✔️
StringDictionary ✔️

* Wenn BitVector32 deserialisiert wird, wird die Data-Eigenschaft übersprungen, weil sie keinen öffentlichen Setter hat. Es wird keine Ausnahme ausgelöst.

System.Collections.Concurrent-Namespace

type Serialisierung Deserialisierung
BlockingCollection<T> ✔️
ConcurrentBag<T> ✔️
ConcurrentDictionary<TKey,TValue> ✔️ ✔️
ConcurrentQueue<T> ✔️ ✔️
ConcurrentStack<T> * ✔️ ✔️

* Siehe Supportroundtrip für Stack-Typen.

† Siehe Unterstützte Schlüsseltypen.

System.Collections.ObjectModel-Namespace

type Serialisierung Deserialisierung
Collection<T> ✔️ ✔️
KeyedCollection<string, TValue> * ✔️
ObservableCollection<T> ✔️ ✔️
ReadOnlyCollection<T> ✔️
ReadOnlyDictionary<TKey,TValue> ✔️
ReadOnlyObservableCollection<T> ✔️

* Es werden nur string-Schlüssel unterstützt.

Benutzerdefinierte Sammlungen

Alle Sammlungen, die sich nicht in einem der zuvor genannten Namespaces befinden, werden als benutzerdefinierte Sammlungen betrachtet. Zu diesen Typen gehören benutzerdefinierte Typen und Typen, die von ASP.NET Core definiert werden. Microsoft.Extensions.Primitives gehört z. B. in diese Gruppe.

Alle benutzerdefinierten Sammlungen (alles, was von IEnumerable abgeleitet wird) werden für die Serialisierung unterstützt, solange ihre Elementtypen unterstützt werden.

Benutzerdefinierte Sammlungen mit Deserialisierungsunterstützung

Eine benutzerdefinierte Sammlung wird für die Deserialisierung unterstützt, wenn:

Benutzerdefinierte Sammlungen mit bekannten Problemen

Es gibt bekannte Probleme mit den folgenden benutzerdefinierten Sammlungen:

Weitere Informationen zu bekannten Problemen finden Sie in den offenen Problemen in System.Text.Json.

Unterstützte Schlüsseltypen

Für die Schlüssel von Dictionary- und SortedList-Typen werden u. a. folgende Typen unterstützt:

  • Boolean
  • Byte
  • DateTime
  • DateTimeOffset
  • Decimal
  • Double
  • Enum
  • Guid
  • Int16
  • Int32
  • Int64
  • Object (nur bei der Serialisierung und, wenn der Laufzeittyp einer der unterstützten Typen in dieser Liste ist)
  • SByte
  • Single
  • String
  • UInt16
  • UInt32
  • UInt64

System.Data-Namespace

Es gibt keine integrierten Konverter für DataSet, DataTable und verwandte Typen im System.Data-Namespace. Wie im Sicherheitsleitfaden erläutert, ist das Deserialisieren dieser Typen aus nicht vertrauenswürdigen Eingaben nicht sicher. Sie können jedoch einen benutzerdefinierten Konverter schreiben, um diese Typen zu unterstützen. Beispielcode für benutzerdefinierten Konverter, der ein DataTable-Element serialisiert und deserialisiert, finden Sie unter RoundtripDataTable.cs.

Siehe auch