Types de collection pris en charge dans System.Text.Json

Cet article donne une vue d’ensemble des collections prises en charge pour la sérialisation et la désérialisation. System.Text.Json.JsonSerializer prend en charge un type de collection pour la sérialisation si :

Le sérialiseur appelle la méthode GetEnumerator() et écrit les éléments.

La désérialisation est plus compliquée et n’est pas prise en charge pour certains types de collection.

Les sections suivantes sont organisées par espace de noms et indiquent les types pris en charge pour la sérialisation et la désérialisation.

Espace de noms System.Array

Type Sérialisation Désérialisation
Tableaux unidimensionnels ✔️ ✔️
Tableaux multidimensionnels
Tableaux en escalier ✔️ ✔️

Espace de noms System.Collections

Type Sérialisation Désérialisation
ArrayList ✔️ ✔️
BitArray ✔️
DictionaryEntry ✔️ ✔️
Hashtable ✔️ ✔️
ICollection ✔️ ✔️
IDictionary ✔️ ✔️
IEnumerable ✔️ ✔️
IList ✔️ ✔️
Queue ✔️ ✔️
SortedList ✔️ ✔️
Stack * ✔️ ✔️

* Voir Support à l’aller-retour pour Stack types.

Espace de noms System.Collections.Generic

Type Sérialisation Désérialisation
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> ✔️ ✔️

* Consultez Types de clés pris en charge.

† Consultez la section suivante sur IAsyncEnumerable<T>.

† Voir Support à l’aller-retour pour Stack types.

IAsyncEnumerable<T>

Les exemples suivants utilisent des flux comme représentation de n’importe quelle source de données asynchrone. La source peut être des fichiers sur un ordinateur local ou des résultats d’une requête de base de données ou d’un appel d’API de service web.

Sérialisation de flux

System.Text.Json prend en charge la sérialisation des valeurs IAsyncEnumerable<T> en tant que tableaux JSON, comme illustré dans l’exemple suivant :

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

Les valeurs IAsyncEnumerable<T> sont uniquement prises en charge par les méthodes de sérialisation asynchrones, telles que JsonSerializer.SerializeAsync.

Désérialisation de flux

La méthode DeserializeAsyncEnumerable prend en charge la désérialisation en streaming, comme illustré dans l’exemple suivant :

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

La méthode DeserializeAsyncEnumerable prend uniquement en charge la lecture à partir de tableaux JSON de niveau racine.

La méthode DeserializeAsync prend en charge IAsyncEnumerable<T>, mais sa signature n’autorise pas la diffusion en continu. Il retourne le résultat final sous la forme d’une valeur unique, comme illustré dans l’exemple suivant.

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

Dans cet exemple, le désérialiseur met en mémoire tampon tout le contenu IAsyncEnumerable<T> avant de renvoyer l’objet désérialisé. Ce comportement est nécessaire, car le désérialiseur doit lire l’intégralité de la charge utile JSON avant de retourner un résultat.

Espace de noms System.Collections.Immutable

Type Sérialisation Désérialisation
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> * ✔️ ✔️

* Voir Support à l’aller-retour pour Stack types.

† Consultez Types de clés pris en charge.

Espace de noms System.Collections.Specialized

Type Sérialisation Désérialisation
BitVector32 ✔️ ❌*
HybridDictionary ✔️ ✔️
IOrderedDictionary ✔️
ListDictionary ✔️ ✔️
NameValueCollection ✔️
StringCollection ✔️
StringDictionary ✔️

* Quand BitVector32 est désérialisé, la propriété Data est ignorée, car elle n’a pas de setter public. Aucune exception n’est générée.

Espace de noms System.Collections.Concurrent

Type Sérialisation Désérialisation
BlockingCollection<T> ✔️
ConcurrentBag<T> ✔️
ConcurrentDictionary<TKey,TValue> ✔️ ✔️
ConcurrentQueue<T> ✔️ ✔️
ConcurrentStack<T> * ✔️ ✔️

* Voir Support à l’aller-retour pour Stack types.

† Consultez Types de clés pris en charge.

Espace de noms System.Collections.ObjectModel

Type Sérialisation Désérialisation
Collection<T> ✔️ ✔️
Chaîne KeyedCollection<, TValue> * ✔️
ObservableCollection<T> ✔️ ✔️
ReadOnlyCollection<T> ✔️
ReadOnlyDictionary<TKey,TValue> ✔️
ReadOnlyObservableCollection<T> ✔️

* Les clés non-string ne sont pas prises en charge.

Regroupements personnalisés

Tout type de collection qui ne se trouve pas dans l’un des espaces de noms précédents est considéré comme une collection personnalisée. Ces types incluent les types définis par l’utilisateur et les types définis par ASP.NET Core. Par exemple, Microsoft.Extensions.Primitives est dans ce groupe.

Toutes les collections personnalisées (tout ce qui dérive de IEnumerable) sont prises en charge pour la sérialisation, tant que leurs types d’éléments sont pris en charge.

Collections personnalisées avec prise en charge de la désérialisation

Une collection personnalisée est prise en charge pour la désérialisation si elle :

Collections personnalisées avec des problèmes connus

Il existe des problèmes connus avec les collections personnalisées suivantes :

Pour plus d’informations sur les problèmes connus, consultez les problèmes ouverts dans System.Text.Json.

Types de clés pris en charge

Parmi les types de clés Dictionary et SortedList, voici ceux pris en charge :

  • Boolean
  • Byte
  • DateTime
  • DateTimeOffset
  • Decimal
  • Double
  • Enum
  • Guid
  • Int16
  • Int32
  • Int64
  • Object (Uniquement sur la sérialisation et si le type d’exécution est l’un des types pris en charge dans cette liste.)
  • SByte
  • Single
  • String
  • UInt16
  • UInt32
  • UInt64

System.Data, espace de noms

Il n’existe aucun convertisseur intégré pour DataSet, DataTableet les types associés dans l’espace de noms XML System.Data. La désérialisation de ces types à partir d’une entrée non approuvée n’est pas sécurisée, comme expliqué dans les consignes de sécurité. Toutefois, vous pouvez écrire un convertisseur personnalisé pour prendre en charge ces types. Pour obtenir un exemple de code de convertisseur personnalisé qui sérialise et désérialise un DataTable, consultez RoundtripDataTable.cs.

Voir aussi