Tipos de coleção compatíveis em System.Text.Json
Este artigo fornece uma visão geral de quais coleções têm suporte para serialização e desserialização. System.Text.Json.JsonSerializer dá suporte a um tipo de coleção para serialização se ele:
- Deriva de IEnumerable ou IAsyncEnumerable<T>
- Contém elementos serializáveis.
O serializador chama o método GetEnumerator() e grava os elementos.
A desserialização é mais complicada e não tem suporte para alguns tipos de coleção.
As seções a seguir são organizadas pelo namespace e mostram quais tipos têm suporte para serialização e desserialização.
Namespace System.Array
Tipo | Serialização | Desserialização |
---|---|---|
Matrizes unidimensionais | ✔️ | ✔️ |
Matrizes multidimensionais | ❌ | ❌ |
Matrizes denteadas | ✔️ | ✔️ |
Namespace System.Collections
Tipo | Serialização | Desserialização |
---|---|---|
ArrayList | ✔️ | ✔️ |
BitArray | ✔️ | ❌ |
DictionaryEntry | ✔️ | ✔️ |
Hashtable | ✔️ | ✔️ |
ICollection | ✔️ | ✔️ |
IDictionary | ✔️ | ✔️ |
IEnumerable | ✔️ | ✔️ |
IList | ✔️ | ✔️ |
Queue | ✔️ | ✔️ |
SortedList | ✔️ | ✔️ |
Stack * | ✔️ | ✔️ |
* Consulte Suporte para ida e volta de Stack
tipos.
Namespace System.Collections.Generic
Tipo | Serialização | Desserialização |
---|---|---|
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 chave com suporte.
† Consulte a seção a seguir sobre IAsyncEnumerable<T>
.
‡ Consulte Suporte de ida e volta para Stack
tipos.
IAsyncEnumerable<T>
Os exemplos a seguir usam fluxos como uma representação de qualquer fonte assíncrona de dados. A origem pode ser arquivos em um computador local ou resultados de uma consulta de banco de dados ou chamada à API do serviço Web.
Serialização de fluxo
System.Text.Json
dá suporte à serialização de valores IAsyncEnumerable<T> como matrizes JSON, conforme mostrado no exemplo a seguir:
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>
os valores têm suporte apenas pelos métodos de serialização assíncronos, como JsonSerializer.SerializeAsync.
Desserialização de fluxo
O método DeserializeAsyncEnumerable
dá suporte à desserialização de streaming, conforme mostrado no exemplo a seguir:
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
O método DeserializeAsyncEnumerable
só dá suporte à leitura de matrizes JSON no nível raiz.
O método DeserializeAsync dá suporte a IAsyncEnumerable<T>
, mas sua assinatura não permite streaming. Ele retorna o resultado final como um único valor, conforme mostrado no exemplo a seguir.
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
Neste exemplo, o desserializador armazena em buffer todo o conteúdo IAsyncEnumerable<T>
na memória antes de retornar o objeto desserializado. Esse comportamento é necessário porque o desserializador precisa ler todo o conteúdo JSON antes de retornar um resultado.
Namespace System.Collections.Immutable
Tipo | Serialização | Desserialização |
---|---|---|
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 Suporte para ida e volta de Stack
tipos.
† Consulte Tipos de chave com suporte.
Namespace System.Collections.Specialized
Tipo | Serialização | Desserialização |
---|---|---|
BitVector32 | ✔️ | ❌* |
HybridDictionary | ✔️ | ✔️ |
IOrderedDictionary | ✔️ | ❌ |
ListDictionary | ✔️ | ✔️ |
NameValueCollection | ✔️ | ❌ |
StringCollection | ✔️ | ❌ |
StringDictionary | ✔️ | ❌ |
* Quando BitVector32 está desserializada, a propriedade Data é ignorada porque não tem um setter público. Nenhuma exceção é gerada.
Namespace System.Collections.Concurrent
Tipo | Serialização | Desserialização |
---|---|---|
BlockingCollection<T> | ✔️ | ❌ |
ConcurrentBag<T> | ✔️ | ❌ |
ConcurrentDictionary<TKey,TValue> † | ✔️ | ✔️ |
ConcurrentQueue<T> | ✔️ | ✔️ |
ConcurrentStack<T> * | ✔️ | ✔️ |
* Consulte Suporte para ida e volta de Stack
tipos.
† Consulte Tipos de chave com suporte.
Namespace System.Collections.ObjectModel
Tipo | Serialização | Desserialização |
---|---|---|
Collection<T> | ✔️ | ✔️ |
Cadeia de caracteres KeyedCollection<, TValue> * | ✔️ | ❌ |
ObservableCollection<T> | ✔️ | ✔️ |
ReadOnlyCollection<T> | ✔️ | ❌ |
ReadOnlyDictionary<TKey,TValue> | ✔️ | ❌ |
ReadOnlyObservableCollection<T> | ✔️ | ❌ |
* Não há suporte para chaves não string
.
Coleções personalizadas
Qualquer tipo de coleção que não esteja em um dos namespaces anteriores é considerado uma coleção personalizada. Esses tipos incluem tipos definidos pelo usuário e tipos definidos por ASP.NET Core. Por exemplo, Microsoft.Extensions.Primitives está nesse grupo.
Todas as coleções personalizadas (tudo o que deriva de IEnumerable
) têm suporte para serialização, desde que seus tipos de elementos sejam compatíveis.
Coleções personalizadas com suporte à desserialização
Uma coleção personalizada terá suporte à desserialização se ela:
Não for uma interface ou abstrata.
Tiver um construtor sem parâmetros.
Contiver tipos de elementos compatíveis com JsonSerializer.
Implementar ou herdar uma ou mais das seguintes interfaces ou classes:
- ConcurrentQueue<T>
- ConcurrentStack<T> *
- ICollection<T>
- IDictionary
- IDictionary<TKey,TValue> †
- IList
- IList<T>
- Queue
- Queue<T>
- Stack *
- Stack<T> *
* Consulte Suporte para ida e volta de
Stack
tipos.† Consulte Tipos de chave com suporte.
Coleções personalizadas com problemas conhecidos
Há problemas conhecidos com as seguintes coleções 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 obter mais informações sobre problemas conhecidos, consulte problemas em aberto em System.Text.Json.
Tipos de chave com suporte
Os tipos com suporte para as chaves Dictionary
e SortedList
tipos incluem o seguinte:
Boolean
Byte
DateTime
DateTimeOffset
Decimal
Double
Enum
Guid
Int16
Int32
Int64
Object
(Somente na serialização e se o tipo de runtime for um dos tipos com suporte nesta lista.)SByte
Single
String
UInt16
UInt32
UInt64
Namespace System.Data
Não há conversores internos para DataSet,DataTable e tipos relacionados no namespace System.Data. Desserializar esses tipos a partir de entrada não confiável não é seguro, conforme explicado nas diretrizes de segurança. No entanto, você pode escrever um conversor personalizado para dar suporte a esses tipos. Para obter um código de conversor personalizado de exemplo que serializa e desserializa um DataTable
, consulte RoundtripDataTable.cs.