Udostępnij za pośrednictwem


Serializacja polimorficzna dla typów obiektów

Przy użyciu konfiguracji System.Text.Json domyślnej serializuje wartości typu object przy użyciu polimorfizmu. To zachowanie staje się mniej spójne w przypadku zarejestrowania niestandardowego konwertera dla programu object. System.Text.Json ma historycznie zakodowany polimorfizm dla wartości obiektów na poziomie głównym, ale nie dla zagnieżdżonych wartości obiektów. Począwszy od platformy .NET 7, to zachowanie zmieniło się tak, aby konwertery niestandardowe nigdy nie używały polimorfizmu.

Poprzednie zachowanie

Rozważmy następujący konwerter obiektów niestandardowych:

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

W poprzednich wersjach następujący kod serializowany jako 0. To dlatego, że serializator używał polimorfizmu i ignorował konwerter niestandardowy.

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

Jednak następujący kod serializowany jako 42, ponieważ serializator honorował konwerter niestandardowy.

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

Nowe zachowanie

Począwszy od platformy .NET 7, używając konwertera obiektów niestandardowych zdefiniowanych w sekcji Poprzednie zachowanie , poniższy kod serializuje jako 42. Dzieje się tak, ponieważ serializator zawsze skonsultuje się z konwerterem niestandardowym i nie używa polimorfizmu.

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

Wprowadzona wersja

.NET 7

Typ zmiany powodującej niezgodność

Ta zmiana może mieć wpływ na zgodność binarną.

Przyczyna wprowadzenia zmiany

Ta zmiana została wprowadzona z powodu niespójnych kontraktów serializacji dla typu, w zależności od tego, czy była serializowana jako wartość na poziomie głównym, czy wartość zagnieżdżona.

W razie potrzeby można odzyskać polimorfizm dla wartości na poziomie głównym, wywołując jedną z nietypowych metod serializacji:

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

Dotyczy interfejsów API