Comparteix a través de


Tipos de recopilación que se admiten en System.Text.Json

En este artículo se proporciona información general sobre qué recopilaciones se admiten para la serialización y deserialización. System.Text.Json.JsonSerializer admite un tipo de recopilación para la serialización si:

El serializador llama al método GetEnumerator() y escribe los elementos.

La deserialización es más complicada y no se admite para algunos tipos de recopilación.

Las secciones siguientes se organizan por espacio de nombres y muestran qué tipos se admiten para la serialización y deserialización.

Espacio de nombres System.Array

Tipo Serialización Deserialización
Matrices unidimensionales ✔️ ✔️
Matrices multidimensionales
Matrices escalonadas ✔️ ✔️

Espacio de nombres System.Collections

Tipo Serialización Deserialización
ArrayList ✔️ ✔️
BitArray ✔️
DictionaryEntry ✔️ ✔️
Hashtable ✔️ ✔️
ICollection ✔️ ✔️
IDictionary ✔️ ✔️
IEnumerable ✔️ ✔️
IList ✔️ ✔️
Queue ✔️ ✔️
SortedList ✔️ ✔️
Stack * ✔️ ✔️

* Consulte Compatibilidad con el recorrido de ida y vuelta para tipos Stack.

Espacio de nombres System.Collections.Generic

Tipo Serialización Deserialización
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> ✔️ ✔️

* Consulte Tipos de clave admitidos.

† Consulte la siguiente sección sobre IAsyncEnumerable<T>.

‡ Consulte Compatibilidad con el recorrido de ida y vuelta para tipos Stack.

IAsyncEnumerable<T>

En los ejemplos siguientes se usan secuencias como representación de cualquier origen asincrónico de datos. El origen podría ser archivos en una máquina local o resultados de una consulta de base de datos o una llamada API de servicio web.

Serialización de secuencias

System.Text.Json admite la serialización de valores IAsyncEnumerable<T> como matrices JSON, como se muestra en el ejemplo siguiente:

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

Los valores IAsyncEnumerable<T> solo son compatibles con los métodos de serialización asincrónica, como JsonSerializer.SerializeAsync.

Deserialización de secuencias

El método DeserializeAsyncEnumerable admite la deserialización de streaming, como se muestra en el ejemplo siguiente:

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

El método DeserializeAsyncEnumerable solo admite la lectura de matrices JSON de nivel raíz.

El método DeserializeAsync admite IAsyncEnumerable<T>, pero su firma no permite el streaming. Devuelve el resultado final como un valor único, como se muestra en el ejemplo siguiente.

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

En este ejemplo, el deserializador almacena en el búfer todo el contenido de IAsyncEnumerable<T> de la memoria antes de devolver el objeto deserializado. Este comportamiento es necesario ya que el deserializador debe leer toda la carga JSON antes de devolver un resultado.

Espacio de nombres System.Collections.Immutable

Tipo Serialización Deserialización
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> * ✔️ ✔️

* Consulte Compatibilidad con el recorrido de ida y vuelta para tipos Stack.

† Consulte Tipos de clave admitidos.

Espacio de nombres System.Collections.Specialized

Tipo Serialización Deserialización
BitVector32 ✔️ ❌*
HybridDictionary ✔️ ✔️
IOrderedDictionary ✔️
ListDictionary ✔️ ✔️
NameValueCollection ✔️
StringCollection ✔️
StringDictionary ✔️

* Cuando BitVector32 se deserializa, se omite la propiedad Data porque no tiene un establecedor público. No se inicia ninguna excepción.

Espacio de nombres System.Collections.Concurrent

Tipo Serialización Deserialización
BlockingCollection<T> ✔️
ConcurrentBag<T> ✔️
ConcurrentDictionary<TKey,TValue> ✔️ ✔️
ConcurrentQueue<T> ✔️ ✔️
ConcurrentStack<T> * ✔️ ✔️

* Consulte Compatibilidad con el recorrido de ida y vuelta para tipos Stack.

† Consulte Tipos de clave admitidos.

Espacio de nombres System.Collections.ObjectModel

Tipo Serialización Deserialización
Collection<T> ✔️ ✔️
KeyedCollection<string, TValue> * ✔️
ObservableCollection<T> ✔️ ✔️
ReadOnlyCollection<T> ✔️
ReadOnlyDictionary<TKey,TValue> ✔️
ReadOnlyObservableCollection<T> ✔️

* No se admiten claves que no sean string.

Recopilaciones personalizadas

Cualquier tipo de recopilación que no se encuentra en uno de los espacios de nombres anteriores se considera una recopilación personalizada. Estos tipos incluyen tipos definidos por el usuario y tipos definidos por ASP.NET Core. Por ejemplo, Microsoft.Extensions.Primitives está en este grupo.

Todas las recopilaciones personalizadas (todas las que derivan de IEnumerable) se admiten para la serialización, siempre y cuando se admitan sus tipos de elementos.

Recopilaciones personalizadas con compatibilidad con la deserialización

Se admite una recopilación personalizada para la deserialización si:

Recopilaciones personalizadas con problemas conocidos

Hay problemas conocidos con las siguientes recopilaciones personalizadas:

Para más información acerca de los problemas conocidos, consulte los problemas abiertos en System.Text.Json.

Tipos de clave admitidos

Entre los tipos admitidos para las claves de los tipos Dictionary y SortedList se incluyen los siguientes:

  • Boolean
  • Byte
  • DateTime
  • DateTimeOffset
  • Decimal
  • Double
  • Enum
  • Guid
  • Int16
  • Int32
  • Int64
  • Object (Solo en la serialización y si el tipo en tiempo de ejecución es uno de los tipos admitidos de esta lista).
  • SByte
  • Single
  • String
  • UInt16
  • UInt32
  • UInt64

Espacio de nombres System.Data

No hay convertidores integrados para DataSet, DataTable y tipos relacionados del espacio de nombres System.Data. La deserialización de estos tipos de entradas que no son de confianza no es segura, como se explica en la guía de seguridad. Sin embargo, puede escribir un convertidor personalizado que admita estos tipos. Para obtener código de convertidor personalizado de ejemplo que serializa y deserializa un DataTable, consulte RoundtripDataTable.cs.

Consulte también