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:
- Deriva de IEnumerable o IAsyncEnumerable<T>.
- Contiene elementos que son serializables.
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:
No es una interfaz ni es abstracta.
Tiene un constructor sin parámetros.
Contiene tipos de elementos que admite JsonSerializer.
Implementa o hereda una o varias de las siguientes interfaces o clases:
- ConcurrentQueue<T>
- ConcurrentStack<T> *
- ICollection<T>
- IDictionary
- IDictionary<TKey,TValue> †
- IList
- IList<T>
- Queue
- Queue<T>
- Stack *
- Stack<T> *
* Consulte Compatibilidad con el recorrido de ida y vuelta para tipos
Stack
.† Consulte Tipos de clave admitidos.
Recopilaciones personalizadas con problemas conocidos
Hay problemas conocidos con las siguientes recopilaciones personalizadas:
- ExpandoObject: Consulte dotnet/runtime#29690.
- DynamicObject: Consulte dotnet/runtime#1808.
- DataTable: Consulte dotnet/docs#21366.
- Microsoft.AspNetCore.Http.FormFile: Consulte dotnet/runtime#1559.
- Microsoft.AspNetCore.Http.IFormCollection: Consulte dotnet/runtime#1559.
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.