Serialização polimórfica para tipos de objeto

Usando a configuração padrão, System.Text.Json serializa valores do tipo objectusando polimorfismo. Esse comportamento se tornará menos consistente se você registrar um conversor personalizado para object. Historicamente, System.Text.Json tem o polimorfismo codificado para valores de objeto no nível da raiz, mas não para valores de objeto aninhados. Começando no .NET 7, esse comportamento foi alterado para que conversores personalizados nunca usem polimorfismo.

Comportamento anterior

Considere o seguinte conversor de objeto personalizado:

public class CustomObjectConverter : JsonConverter<object>
{
    public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOptions options)
        => writer.WriteNumberValue(42);

    public override object Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        => throw new NotImplementedException();
}

Nas versões anteriores, o código a seguir era serializado como 0. Isso ocorria porque o serializador usava polimorfismo e ignorava o conversor personalizado.

var options = new JsonSerializerOptions { Converters = { new CustomObjectConverter() } };
JsonSerializer.Serialize<object>(0, options);

No entanto, o código a seguir era serializado como 42 porque o serializador respeitava o conversor personalizado.

var options = new JsonSerializerOptions { Converters = { new CustomObjectConverter() } };
JsonSerializer.Serialize<object[]>(new object[] { 0 }, options);

Novo comportamento

Começando no .NET 7, usando o conversor de objeto personalizado definido na seção Comportamento anterior, o código a seguir é serializado como 42. Isso ocorre porque o serializador sempre consultará o conversor personalizado e não usará polimorfismo.

var options = new JsonSerializerOptions { Converters = { new CustomObjectConverter() } };
JsonSerializer.Serialize<object>(0, options);

Versão introduzida

.NET 7

Tipo de alteração interruptiva

Essa alteração pode afetar a compatibilidade binária.

Motivo da alteração

Essa alteração foi feita devido a contratos de serialização inconsistentes para um tipo, dependendo de ele ser serializado como um valor no nível da raiz ou um valor aninhado.

Se quiser, você poderá recuperar o polimorfismo para valores no nível da raiz invocando um dos métodos de serialização não tipados:

var options = new JsonSerializerOptions { Converters = { new CustomObjectConverter() } };
JsonSerializer.Serialize(0, inputType: typeof(int), options); // Serializes as 0.

APIs afetadas