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:
- von IEnumerable oder IAsyncEnumerable<T> abgeleitet ist
- Elemente enthält, die serialisierbar sind
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:
sie weder eine Schnittstelle noch abstrakt ist
über einen parameterlosen Konstruktor verfügt
Elementtypen enthält, die von JsonSerializer unterstützt werden
Implementiert oder erbt mindestens eine der folgenden Schnittstellen oder Klassen:
- ConcurrentQueue<T>
- ConcurrentStack<T> *
- ICollection<T>
- IDictionary
- IDictionary<TKey,TValue> †
- IList
- IList<T>
- Queue
- Queue<T>
- Stack *
- Stack<T> *
* Siehe Supportroundtrip für
Stack
-Typen.† Siehe Unterstützte Schlüsseltypen.
Benutzerdefinierte Sammlungen mit bekannten Problemen
Es gibt bekannte Probleme mit den folgenden benutzerdefinierten Sammlungen:
- ExpandoObject: Siehe dotnet/runtime#29690.
- DynamicObject: Siehe dotnet/runtime#1808.
- DataTable: Siehe dotnet/docs#21366.
- Microsoft.AspNetCore.Http.FormFile: Siehe dotnet/runtime#1559.
- Microsoft.AspNetCore.Http.IFormCollection: Siehe dotnet/runtime#1559.
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.