Ondersteunde typen in System.Text.Json

Dit artikel bevat een overzicht van welke typen worden ondersteund voor serialisatie en deserialisatie.

Typen die worden geserialiseerd als JSON-objecten

De volgende typen serialiseren als JSON-objecten:

  • Klassen*
  • Structs
  • Interfaces
  • Records en struct-records

* Niet-woordenlijsttypen die IEnumerable<T> serialiseren als JSON-matrices. Woordenlijsttypen, die IEnumerable<T>implementeren, serialiseren als JSON-objecten.

Het volgende codefragment toont de serialisatie van een eenvoudige struct.

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 worden geserialiseerd als JSON-matrices

.NET-verzamelingstypen serialiseren als JSON-matrices. System.Text.Json.JsonSerializer ondersteunt een verzamelingstype voor serialisatie als dit het volgende is:

De serializer roept de GetEnumerator() methode aan en schrijft de elementen.

Deserialisatie is ingewikkelder en wordt niet ondersteund voor sommige verzamelingstypen.

De volgende secties zijn ingedeeld op naamruimte en laten zien welke typen worden ondersteund voor serialisatie en deserialisatie.

System.Array-naamruimte

Type Serialisatie Deserialisatie
Eendimensionale matrices* ✔️ ✔️
multidimensionale matrices ❌ ❌
gemarkeerde matrices ✔️ ✔️

* byte[] wordt speciaal verwerkt en serialiseert als een base64-tekenreeks, niet als een JSON-matrix.

System.Collections-naamruimte

Type Serialisatie Deserialisatie
ArrayList ✔️ ✔️
BitArray ✔️ ❌
DictionaryEntry ✔️ ✔️
Hashtable ✔️ ✔️
ICollection ✔️ ✔️
IDictionary ✔️ ✔️
IEnumerable ✔️ ✔️
IList ✔️ ✔️
Queue ✔️ ✔️
SortedList ✔️ ✔️
Stack * ✔️ ✔️

* Zie Ondersteuningsrondje voor Stack typen.

System.Collections.Generic-naamruimte

Type Serialisatie Deserialisatie
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> ‡ ✔️ ✔️

* Zie Ondersteunde sleuteltypen.

† Zie de volgende sectie over IAsyncEnumerable<T>.

‡ Zie Ondersteuningsrondje voor Stack typen.

§ System.Text.Json ondersteunt IReadOnlySet<T> in .NET 11 en latere versies. Wanneer u de interface deserialiseert, wordt met de serialisatiefunctie een HashSet<T> exemplaar gemaakt. Voor gegenereerde metagegevens JsonMetadataServices.CreateIReadOnlySetInfo maakt u het verzamelingscontract.

IAsyncEnumerable<T->

In de volgende voorbeelden worden streams gebruikt als een weergave van een asynchrone gegevensbron. De bron kan bestanden op een lokale computer zijn, of resultaten van een databasequery of webservice-API-aanroep.

Stream-serialisatie

System.Text.Json ondersteunt het serialiseren van IAsyncEnumerable<T> waarden als JSON-matrices, zoals wordt weergegeven in het volgende voorbeeld:

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> waarden worden alleen ondersteund door de asynchrone serialisatiemethoden, zoals JsonSerializer.SerializeAsync.

In .NET 11 en latere versies JsonSerializer.SerializeAsyncEnumerable schrijft u een IAsyncEnumerable<T> reeks naar een Stream of een PipeWriter. Met de standaardmethode topLevelValues: falseschrijft de methode één JSON-matrix op hoofdniveau. Stel in plaats daarvan in op topLevelValues: true het schrijven van JSON-lijnen , waarbij elk element een afzonderlijke waarde op het hoogste niveau is:

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

De methode schrijft één regelfeed (LF), \nna elke waarde, inclusief de laatste. Het gebruikt altijd LF, ongeacht JsonSerializerOptions.NewLine. De methode negeert JsonSerializerOptions.WriteIndented, dus elke waarde blijft op één regel staan.

Stroomdeserialisatie

De methode DeserializeAsyncEnumerable ondersteunt streamingdeserialisatie, zoals wordt weergegeven in het volgende voorbeeld:

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

JsonSerializer.DeserializeAsyncEnumerable Leest standaard elementen uit één JSON-matrix op hoofdniveau. Ingesteld topLevelValues: true op het lezen van een reeks door witruimten gescheiden waarden op het hoogste niveau. Deze invoerindeling is een superset van JSON-lijnen. Overbelastingen accepteren een Stream of een PipeReader.

De methode DeserializeAsync ondersteunt IAsyncEnumerable<T>, maar de handtekening staat streaming niet toe. Het uiteindelijke resultaat wordt als één waarde geretourneerd, zoals wordt weergegeven in het volgende voorbeeld.

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 dit voorbeeld buffert deserializer alle IAsyncEnumerable<T> inhoud in het geheugen voordat het gedeserialiseerde object wordt geretourneerd. Dit gedrag is nodig omdat de deserializer de volledige JSON-nettolading moet lezen voordat een resultaat wordt geretourneerd.

System.Collections.Immutable naamruimte

Type Serialisatie Deserialisatie
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> * ✔️ ✔️

* Zie Ondersteuningsrondje voor Stack typen.

† Zie Ondersteunde sleuteltypen.

System.Collections.Specialized-naamruimte

Type Serialisatie Deserialisatie
BitVector32 ✔️ ❌*
HybridDictionary ✔️ ✔️
IOrderedDictionary ✔️ ❌
ListDictionary ✔️ ✔️
NameValueCollection ✔️ ❌
StringCollection ✔️ ❌
StringDictionary ✔️ ❌

* Wanneer BitVector32 wordt gedeserialiseerd, wordt de eigenschap Data overgeslagen omdat deze geen openbare setter heeft. Er wordt geen uitzondering gegenereerd.

System.Collections.Concurrent-naamruimte

Type Serialisatie Deserialisatie
BlockingCollection<T> ✔️ ❌
ConcurrentBag<T> ✔️ ❌
ConcurrentDictionary<TKey,TValue> † ✔️ ✔️
ConcurrentQueue<T> ✔️ ✔️
ConcurrentStack<T> * ✔️ ✔️

* Zie Ondersteuningsrondje voor Stack typen.

† Zie Ondersteunde sleuteltypen.

System.Collections.ObjectModel-naamruimte

Type Serialisatie Deserialisatie
Collection<T> ✔️ ✔️
KeyedCollection<tekenreeks, TValue> * ✔️ ❌
ObservableCollection<T> ✔️ ✔️
ReadOnlyCollection<T> ✔️ ❌
ReadOnlyDictionary<TKey,TValue> ✔️ ❌
ReadOnlyObservableCollection<T> ✔️ ❌

* Niet-string sleutels worden niet ondersteund.

Aangepaste verzamelingen

Een verzamelingstype dat zich niet in een van de voorgaande naamruimten bevindt, wordt beschouwd als een aangepaste verzameling. Dergelijke typen omvatten door de gebruiker gedefinieerde typen en typen die zijn gedefinieerd door ASP.NET Core. Microsoft.Extensions.Primitives bevindt zich bijvoorbeeld in deze groep.

Alle aangepaste verzamelingen (alles wat is afgeleid van IEnumerable) worden ondersteund voor serialisatie, zolang hun elementtypen worden ondersteund.

Ondersteuning voor deserialisatie

Een aangepaste verzameling wordt ondersteund voor deserialisatie als deze:

Bekende problemen

Er zijn bekende problemen met de volgende aangepaste verzamelingen:

Zie de openstaande problemen in System.Text.Jsonvoor meer informatie over bekende problemen.

Ondersteunde sleuteltypen

Wanneer deze worden gebruikt als sleutels van Dictionary en SortedList typen, hebben de volgende typen ingebouwde ondersteuning:

  • BFloat16(.NET 11 en hoger)
  • Boolean
  • Byte
  • DateTime
  • DateTimeOffset
  • Decimal
  • Decimal32(.NET 11 en hoger)
  • Decimal64(.NET 11 en hoger)
  • Decimal128(.NET 11 en hoger)
  • Double
  • Enum
  • Guid
  • Int16
  • Int32
  • Int64
  • Object (alleen bij serialisatie en als het runtimetype een van de ondersteunde typen in deze lijst is.)
  • SByte
  • Single
  • String
  • TimeSpan
  • UInt16
  • UInt32
  • UInt64
  • Uri
  • Version

Bovendien kunt u met de methoden JsonConverter<T>.WriteAsPropertyName(Utf8JsonWriter, T, JsonSerializerOptions) en JsonConverter<T>.ReadAsPropertyName(Utf8JsonReader, Type, JsonSerializerOptions) woordenlijstsleutels toevoegen voor elk type van uw keuze.

BFloat16- en decimale typen drijvende komma

Vanaf .NET 11 bevat System.Text.Json ingebouwde conversieprogramma's voor de BFloat16, Decimal32en Decimal64Decimal128 typen. Eindige waarden serialiseren als JSON-getallen.

Deze typen gedragen zich als de andere ingebouwde numerieke typen:

JsonMetadataServices toont conversie-eigenschappen voor door de bron gegenereerde metagegevens. De eigenschappen zijnJsonMetadataServices.BFloat16Converter, JsonMetadataServices.Decimal32Converter, en JsonMetadataServices.Decimal64ConverterJsonMetadataServices.Decimal128Converter.

F# gediscrimineerde vakbonden

Vanaf .NET 11 System.Text.Json serialiseert en ontserialiseerde F# gediscrimineerde vakbonden, waaronder klasse, struct en recursieve vakbonden:

type Shape =
    | Point
    | Circle of radius: float
  • Een hoofdletter zonder velden serialiseert als een JSON-tekenreeks die de naam van de case bevat, zoals "Point".
  • Een case met velden serialiseert als een JSON-object. Het object bevat een $type discriminator gevolgd door de benoemde velden van de zaak, zoals {"$type":"Circle","radius":3.14}.

JsonSerializerOptions.PropertyNamingPolicy is van toepassing op naamnamen en veldnamen. Een hoofdletterniveau JsonPropertyNameAttribute heeft voorrang. Als u een andere naam van een discriminatoreigenschap wilt gebruiken dan $type, stelt u in JsonPolymorphicAttribute.TypeDiscriminatorPropertyName.

Important

F# gediscrimineerde steun voor de samenvoeging is alleen reflectie. Hiervoor zijn dynamische code en niet-opgehaalde weerspiegelingsmetagegevens vereist. U kunt deze niet gebruiken met System.Text.Json brongeneratie of systeemeigen AOT.

Niet-ondersteunde typen

De volgende typen worden niet ondersteund voor serialisatie:

System.Data-naamruimte

Er zijn geen ingebouwde conversieprogramma's voor DataSet, DataTableen gerelateerde typen in de System.Data-naamruimte. Het deserialiseren van deze typen van niet-vertrouwde invoer is niet veilig, zoals wordt uitgelegd in de beveiligingsrichtlijnen. U kunt echter een aangepast conversieprogramma schrijven om deze typen te ondersteunen. Zie DataTablevoor voorbeeldcode voor aangepaste conversieprogramma's waarmee een wordt geserialiseerd en gedeserialiseerd.

Zie ook