Unterstützte Typen in System.Text.Json

In diesem Artikel finden Sie eine Übersicht darüber, welche Typen für die Serialisierung und Deserialisierung unterstützt werden.

Typen, die als JSON-Objekte serialisiert werden

Die folgenden Typen serialisieren als JSON-Objekte:

  • Klassen*
  • Strukturen
  • Schnittstellen
  • Datensätze und Strukturdatensätze

* Nichtwörterbuchtypen, die IEnumerable<T> als JSON-Arrays serialisieren. Wörterbuchtypen, die IEnumerable<T>implementieren, serialisieren sie als JSON-Objekte.

Der folgende Codeausschnitt zeigt die Serialisierung einer einfachen Struktur.

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; }
}

Typen, die als JSON-Arrays serialisiert werden

.NET-Sammlungstypen serialisieren als JSON-Arrays. System.Text.Json.JsonSerializer unterstützt einen Sammlungstyp für die Serialisierung, wenn er:

Der Serialisierer ruft die GetEnumerator()-Methode auf und schreibt die Elemente.

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

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

System.Array-Namespace

Art Serialisierung Deserialisierung
Eindimensionale Arrays* ✔️ ✔️
mehrdimensionalen Arrays ❌ ❌
Jagged Arrays ✔️ ✔️

* byte[] wird speziell behandelt und als base64-Zeichenfolge und nicht als JSON-Array serialisiert.

System.Collections-Namespace

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

* Siehe Support Roundtrip für Stack Typen.

System.Collections.Generic-Namespace

Art 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> ✔️ ✔️
IReadOnlySet<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.

† Weitere Informationen finden Sie im folgenden Abschnitt zu IAsyncEnumerable<T>.

– Siehe Support Roundtrip für Stack Typen.

§ System.Text.Json unterstützt IReadOnlySet<T> in .NET 11 und neueren Versionen. Wenn Sie die Schnittstelle deserialisieren, erstellt der Serializer eine HashSet<T> Instanz. Erstellt für generierte Metadaten JsonMetadataServices.CreateIReadOnlySetInfo den Sammlungsvertrag.

IAsyncEnumerable<T->

In den folgenden Beispielen werden Datenströme als Darstellung einer asynchronen Datenquelle verwendet. Die Quelle kann Dateien auf einem lokalen Computer oder Ergebnisse aus einem Datenbankabfrage- oder Webdienst-API-Aufruf sein.

Stream serialisierung

System.Text.Json unterstützt die Serialisierung IAsyncEnumerable<T> Werte als JSON-Arrays, wie 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 den asynchronen Serialisierungsmethoden wie JsonSerializer.SerializeAsyncunterstützt.

In .NET 11 und neueren Versionen JsonSerializer.SerializeAsyncEnumerable schreibt eine IAsyncEnumerable<T> Sequenz entweder in eine Stream oder eine PipeWriter. Mit der Standardeinstellung topLevelValues: falseschreibt die Methode ein einzelnes JSON-Array auf Stammebene. Legen Sie topLevelValues: true stattdessen fest, dass JSON-Zeilen geschrieben werden, wobei jedes Element ein separater Wert auf oberster Ebene ist:

{"id":1,"name":"apple"}
{"id":2,"name":"banana"}

Die Methode schreibt einen einzelnen Zeilenvorschub (LF), \nnach jedem Wert, einschließlich des letzten Werts. Es verwendet immer LF, unabhängig von JsonSerializerOptions.NewLine. Die Methode ignoriert JsonSerializerOptions.WriteIndented, sodass jeder Wert in einer Zeile verbleibt.

Stream-Deserialisierung

Die DeserializeAsyncEnumerable-Methode unterstützt die Streaming-Deserialisierung, 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

Liest standardmäßig JsonSerializer.DeserializeAsyncEnumerable Elemente aus einem einzelnen JSON-Array auf Stammebene. Legen Sie diese Einstellung topLevelValues: true fest, um stattdessen eine Sequenz von Leerzeichen getrennten Werten auf oberster Ebene zu lesen. Dieses Eingabeformat ist eine Obermenge von JSON-Zeilen. Überladungen akzeptieren entweder ein Stream oder ein PipeReader.

Die DeserializeAsync-Methode unterstützt IAsyncEnumerable<T>, die Signatur lässt jedoch kein Streaming zu. Das Endergebnis wird als einzelner Wert zurückgegeben, wie im folgenden Beispiel gezeigt.

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 Deserializer alle IAsyncEnumerable<T> Inhalte im Arbeitsspeicher, bevor das deserialisierte Objekt zurückgegeben wird. Dieses Verhalten ist erforderlich, da der Deserializer die gesamte JSON-Nutzlast lesen muss, bevor ein Ergebnis zurückgegeben wird.

System.Collections.Immutable Namespace

Art 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 Support Roundtrip für Stack Typen.

† Siehe Unterstützte Schlüsseltypen.

System.Collections.Specialized-Namespace

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

* Wenn BitVector32 deserialisiert wird, wird die Data-Eigenschaft übersprungen, da kein öffentlicher Setter vorhanden ist. Es wird keine Ausnahme ausgelöst.

System.Collections.Gleichzeitiger Namespace

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

* Siehe Support Roundtrip für Stack Typen.

† Siehe Unterstützte Schlüsseltypen.

System.Collections.ObjectModel-Namespace

Art Serialisierung Deserialisierung
Collection<T> ✔️ ✔️
KeyedCollection<Zeichenfolge, TValue> * ✔️ ❌
ObservableCollection<T> ✔️ ✔️
ReadOnlyCollection<T> ✔️ ❌
ReadOnlyDictionary<TKey,TValue> ✔️ ❌
ReadOnlyObservableCollection<T> ✔️ ❌

* Nichtstring Schlüssel werden nicht unterstützt.

Benutzerdefinierte Auflistungen

Jeder Sammlungstyp, der sich nicht in einem der vorherigen Namespaces befindet, wird als benutzerdefinierte Auflistung betrachtet. Zu diesen Typen gehören benutzerdefinierte Typen und Typen, die von ASP.NET Core definiert werden. Beispielsweise befindet sich Microsoft.Extensions.Primitives in dieser Gruppe.

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

Deserialisierungsunterstützung

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

Bekannte Probleme

Es gibt bekannte Probleme mit den folgenden benutzerdefinierten Auflistungen:

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

Unterstützte Schlüsseltypen

Bei Verwendung als Schlüssel von Dictionary- und SortedList Typen haben die folgenden Typen integrierte Unterstützung:

  • BFloat16(.NET 11 und höher)
  • Boolean
  • Byte
  • DateTime
  • DateTimeOffset
  • Decimal
  • Decimal32(.NET 11 und höher)
  • Decimal64(.NET 11 und höher)
  • Decimal128(.NET 11 und höher)
  • Double
  • Enum
  • Guid
  • Int16
  • Int32
  • Int64
  • Object (Nur bei serialisierung und wenn der Laufzeittyp einer der unterstützten Typen in dieser Liste ist.)
  • SByte
  • Single
  • String
  • TimeSpan
  • UInt16
  • UInt32
  • UInt64
  • Uri
  • Version

Darüber hinaus können Sie mit den Methoden JsonConverter<T>.WriteAsPropertyName(Utf8JsonWriter, T, JsonSerializerOptions) und JsonConverter<T>.ReadAsPropertyName(Utf8JsonReader, Type, JsonSerializerOptions) Wörterbuchschlüsselunterstützung für jede Art Ihrer Wahl hinzufügen.

BFloat16- und Dezimalkomma-Gleitkommatypen

Ab .NET 11 System.Text.Json sind integrierte Konverter für die BFloat16, Decimal32, , Decimal64und Decimal128 Typen enthalten. Endliche Werte serialisieren als JSON-Zahlen.

Diese Typen verhalten sich wie die anderen integrierten numerischen Typen:

JsonMetadataServices macht Konvertereigenschaften für vom Quell generierte Metadaten verfügbar. Die Eigenschaften sind JsonMetadataServices.BFloat16Converter, JsonMetadataServices.Decimal32Converter, JsonMetadataServices.Decimal64Converter und JsonMetadataServices.Decimal128Converter.

F# diskriminierte Gewerkschaften

Beginnend mit .NET 11 System.Text.Json serialisiert und deserialisiert F#diskriminierte Gewerkschaften, einschließlich Klassen-, Struktur- und rekursive Gewerkschaften:

type Shape =
    | Point
    | Circle of radius: float
  • Ein Fall ohne Felder serialisiert als JSON-Zeichenfolge, die den Fallnamen enthält, z "Point". B. .
  • Ein Fall, in dem Felder als JSON-Objekt serialisiert werden. Das Objekt enthält einen $type Diskriminator gefolgt von den benannten Feldern des Falls, z {"$type":"Circle","radius":3.14}. B. .

JsonSerializerOptions.PropertyNamingPolicy gilt für Groß- und Kleinschreibungsnamen und Feldnamen. Eine Fallebene JsonPropertyNameAttribute hat Vorrang. Wenn Sie einen anderen Namen als die Diskriminatoreigenschaft verwenden $typemöchten, legen Sie fest JsonPolymorphicAttribute.TypeDiscriminatorPropertyName.

Important

F# diskriminierte Union-Unterstützung ist nur spiegelungsgeschützt. Es erfordert dynamischen Code und unbetrimmte Spiegelungsmetadaten. Sie können es nicht mit System.Text.Json der Quellgenerierung oder nativen AOT verwenden.

Nicht unterstützte Typen

Die folgenden Typen werden für die Serialisierung nicht unterstützt:

System.Data-Namespace

Es gibt keine integrierten Konverter für DataSet, DataTableund verwandte Typen im System.Data-Namespace. Das Deserialisieren dieser Typen von nicht vertrauenswürdigen Eingaben ist nicht sicher, wie in der Sicherheitsleitfadenerläutert. Sie können jedoch einen benutzerdefinierten Konverter schreiben, um diese Typen zu unterstützen. Beispielcode für benutzerdefinierte Konverter, der eine DataTableserialisiert und deserialisiert, finden Sie unter RoundtripDataTable.cs.

Siehe auch