Полиморфная сериализация для типов объектов

Используя конфигурацию по умолчанию, System.Text.Json сериализует значения типа objectс помощью полиморфизма. Это поведение становится менее согласованным при регистрации пользовательского преобразователя для object. System.Text.Json имеет исторически жестко закодированный полиморфизм для значений объектов корневого уровня, но не для вложенных значений объектов. Начиная с .NET 7 это поведение изменилось так, чтобы пользовательские преобразователи никогда не использовали полиморфизм.

Прежнее поведение

Рассмотрим следующий настраиваемый преобразователь объектов:

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();
}

В предыдущих версиях следующий код сериализуется как 0. Это связано с тем, что сериализатор использовал полиморфизм и проигнорировал пользовательский преобразователь.

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

Однако следующий код сериализуется как 42, так как сериализатор учитывает настраиваемый преобразователь.

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

Новое поведение

Начиная с .NET 7, используя настраиваемый преобразователь объектов, определенный в разделе "Предыдущее поведение ", следующий код сериализуется как 42. Это связано с тем, что сериализатор всегда будет обращаться к пользовательскому преобразователю и не использовать полиморфизм.

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

Представленные версии

.NET 7

Тип критического изменения

Это изменение может повлиять на совместимость двоичного кода.

Причина изменения

Это изменение было внесено из-за несогласованных контрактов сериализации для типа в зависимости от того, сериализуется ли он в качестве значения корневого уровня или вложенного значения.

При необходимости можно вернуть полиморфизм для значений корневого уровня, вызвав один из нетипизированных методов сериализации:

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

Затронутые API