Taal

Eigenschappen van afgeleide klassen serialiseren met System.Text.Json

In dit artikel leert u hoe u eigenschappen van afgeleide klassen serialiseert met de System.Text.Json naamruimte.

Eigenschappen van afgeleide klassen serialiseren

Vanaf .NET 7 ondersteunt System.Text.Json polymorfe hiërarchieserialisatie en deserialisatie met kenmerkaantekeningen.

Kenmerk Beschrijving
JsonDerivedTypeAttribute Wanneer dit op een typedeclaratie wordt geplaatst, geeft dit aan dat het opgegeven subtype expliciet moet worden ingeschakeld voor polymorfe serialisatie. Het geeft ook de mogelijkheid om een typediscriminator op te geven.
JsonPolymorphicAttribute Wanneer dit op een typedeclaratie wordt toegepast, geeft dit aan dat het type polymorf moet worden geserialiseerd. Er worden ook verschillende opties weergegeven voor het configureren van polymorfische serialisatie en deserialisatie voor dat type.

Stel dat u een WeatherForecastBase klasse en een afgeleide klasse WeatherForecastWithCityhebt:

[JsonDerivedType(typeof(WeatherForecastWithCity))]
public class WeatherForecastBase
{
    public DateTimeOffset Date { get; set; }
    public int TemperatureCelsius { get; set; }
    public string? Summary { get; set; }
}
<JsonDerivedType(GetType(WeatherForecastWithCity))>
Public Class WeatherForecastBase
    Public Property [Date] As DateTimeOffset
    Public Property TemperatureCelsius As Integer
    Public Property Summary As String
End Class
public class WeatherForecastWithCity : WeatherForecastBase
{
    public string? City { get; set; }
}
Public Class WeatherForecastWithCity
    Inherits WeatherForecastBase
    Public Property City As String
End Class

Stel dat het typeargument van de Serialize<TValue> methode tijdens het compileren het volgende is WeatherForecastBase:

options = new JsonSerializerOptions
{
    WriteIndented = true
};
jsonString = JsonSerializer.Serialize<WeatherForecastBase>(weatherForecastBase, options);
options = New JsonSerializerOptions With {
    .WriteIndented = True
}
jsonString = JsonSerializer.Serialize(WeatherForecastBase, options)

In dit scenario wordt de City eigenschap geserialiseerd omdat het weatherForecastBase object eigenlijk een WeatherForecastWithCity object is. Deze configuratie maakt polymorfische serialisatie mogelijk voorWeatherForecastBase, met name wanneer het runtimetype:WeatherForecastWithCity

{
  "City": "Milwaukee",
  "Date": "2022-09-26T00:00:00-05:00",
  "TemperatureCelsius": 15,
  "Summary": "Cool"
}

Hoewel round-tripping van de payload wordt WeatherForecastBase ondersteund, wordt deze niet als een runtime-type van WeatherForecastWithCity gerealiseerd. In plaats daarvan wordt het gerealiseerd als een runtimetype van WeatherForecastBase:

WeatherForecastBase value = JsonSerializer.Deserialize<WeatherForecastBase>("""
    {
      "City": "Milwaukee",
      "Date": "2022-09-26T00:00:00-05:00",
      "TemperatureCelsius": 15,
      "Summary": "Cool"
    }
    """);

Console.WriteLine(value is WeatherForecastWithCity); // False
Dim value As WeatherForecastBase = JsonSerializer.Deserialize(@"
    {
      "City": "Milwaukee",
      "Date": "2022-09-26T00:00:00-05:00",
      "TemperatureCelsius": 15,
      "Summary": "Cool"
    }")

Console.WriteLine(value is WeatherForecastWithCity) // False

In het volgende gedeelte wordt beschreven hoe u metagegevens toevoegt waarmee heen-en-terugconversie van het afgeleide type mogelijk wordt.

Polymorfische typediscriminatoren

Als u polymorfische deserialisatie wilt inschakelen, moet u een typediscriminatie opgeven voor de afgeleide klasse:

[JsonDerivedType(typeof(WeatherForecastBase), typeDiscriminator: "base")]
[JsonDerivedType(typeof(WeatherForecastWithCity), typeDiscriminator: "withCity")]
public class WeatherForecastBase
{
    public DateTimeOffset Date { get; set; }
    public int TemperatureCelsius { get; set; }
    public string? Summary { get; set; }
}

public class WeatherForecastWithCity : WeatherForecastBase
{
    public string? City { get; set; }
}
<JsonDerivedType(GetType(WeatherForecastBase), "base")>
<JsonDerivedType(GetType(WeatherForecastWithCity), "withCity")>
Public Class WeatherForecastBase
    Public Property [Date] As DateTimeOffset
    Public Property TemperatureCelsius As Integer
    Public Property Summary As String
End Class

Public Class WeatherForecastWithCity
    Inherits WeatherForecastBase
    Public Property City As String
End Class

Met de toegevoegde metagegevens, met name de typediscriminator, kan de serializer de payload serialiseren en deserialiseren als het type WeatherForecastWithCity op basis van het basistype WeatherForecastBase. Serialisatie verzendt JSON samen met de typediscriminatiemetagegevens:

WeatherForecastBase weather = new WeatherForecastWithCity
{
    City = "Milwaukee",
    Date = new DateTimeOffset(2022, 9, 26, 0, 0, 0, TimeSpan.FromHours(-5)),
    TemperatureCelsius = 15,
    Summary = "Cool"
}
var json = JsonSerializer.Serialize<WeatherForecastBase>(weather, options);
Console.WriteLine(json);
// Sample output:
//   {
//     "$type" : "withCity",
//     "City": "Milwaukee",
//     "Date": "2022-09-26T00:00:00-05:00",
//     "TemperatureCelsius": 15,
//     "Summary": "Cool"
//   }
Dim weather As WeatherForecastBase = New WeatherForecastWithCity With
{
    .City = "Milwaukee",
    .[Date] = New DateTimeOffset(2022, 9, 26, 0, 0, 0, TimeSpan.FromHours(-5)),
    .TemperatureCelsius = 15,
    .Summary = "Cool"
}
Dim json As String = JsonSerializer.Serialize(weather, options)
Console.WriteLine(json)
' Sample output:
'   {
'     "$type" : "withCity",
'     "City": "Milwaukee",
'     "Date": "2022-09-26T00:00:00-05:00",
'     "TemperatureCelsius": 15,
'     "Summary": "Cool"
'   }

Met de typediscriminator kan de serializer de payload polymorf deserialiseren als WeatherForecastWithCity:

WeatherForecastBase value = JsonSerializer.Deserialize<WeatherForecastBase>(json);
Console.WriteLine(value is WeatherForecastWithCity); // True
Dim value As WeatherForecastBase = JsonSerializer.Deserialize(json)
Console.WriteLine(value is WeatherForecastWithCity) // True

Notitie

Standaard moet de $type discriminator aan het begin van het JSON-object worden geplaatst, gegroepeerd samen met andere metagegevenseigenschappen, zoals $id en $ref. Als u gegevens leest van een externe API die de $type discriminator in het midden van het JSON-object plaatst, stelt u JsonSerializerOptions.AllowOutOfOrderMetadataPropertiestruehet volgende in:

JsonSerializerOptions options = new() { AllowOutOfOrderMetadataProperties = true };
JsonSerializer.Deserialize<Base>("""{"Name":"Name","$type":"derived"}""", options);

Wees voorzichtig wanneer u deze vlag inschakelt, omdat dit kan leiden tot overbuffering (en onvoldoende geheugenfouten) bij het uitvoeren van streamingdeserialisatie van zeer grote JSON-objecten.

Typediscriminatorindelingen combineren en afstemmen

Type discriminator-id’s zijn geldig in de vorm string of int, dus het volgende is geldig:

[JsonDerivedType(typeof(WeatherForecastWithCity), 0)]
[JsonDerivedType(typeof(WeatherForecastWithTimeSeries), 1)]
[JsonDerivedType(typeof(WeatherForecastWithLocalNews), 2)]
public class WeatherForecastBase { }

var json = JsonSerializer.Serialize<WeatherForecastBase>(new WeatherForecastWithTimeSeries());
Console.WriteLine(json);
// Sample output:
//   {
//    "$type" : 1,
//    Omitted for brevity...
//   }
<JsonDerivedType(GetType(WeatherForecastWithCity), 0)>
<JsonDerivedType(GetType(WeatherForecastWithTimeSeries), 1)>
<JsonDerivedType(GetType(WeatherForecastWithLocalNews), 2)>
Public Class WeatherForecastBase
End Class

Dim json As String = JsonSerializer.Serialize(Of WeatherForecastBase)(New WeatherForecastWithTimeSeries())
Console.WriteLine(json)
' Sample output:
'  {
'    "$type" : 1,
'    Omitted for brevity...
'  }

Hoewel de API ondersteuning biedt voor het combineren en vergelijken van typediscriminatorconfiguraties, wordt dit niet aanbevolen. De algemene aanbeveling is om ofwel alle typediscriminatoren van het type string, alle typediscriminatoren van het type int, of helemaal geen typediscriminatoren te gebruiken. In het volgende voorbeeld ziet u hoe u onderscheidsconfiguraties voor typen combineert en matcht:

[JsonDerivedType(typeof(ThreeDimensionalPoint), typeDiscriminator: 3)]
[JsonDerivedType(typeof(FourDimensionalPoint), typeDiscriminator: "4d")]
public class BasePoint
{
    public int X { get; set; }
    public int Y { get; set; }
}

public class ThreeDimensionalPoint : BasePoint
{
    public int Z { get; set; }
}

public sealed class FourDimensionalPoint : ThreeDimensionalPoint
{
    public int W { get; set; }
}
<JsonDerivedType(GetType(ThreeDimensionalPoint), 3)>
<JsonDerivedType(GetType(FourDimensionalPoint), "4d")>
Public Class BasePoint
    Public Property X As Integer
    Public Property Y As Integer
End Class

Public Class ThreeDimensionalPoint
    Inherits BasePoint
    Public Property Z As Integer
End Class

Public NotInheritable Class FourDimensionalPoint
    Inherits ThreeDimensionalPoint
    Public Property W As Integer
End Class

In het voorgaande voorbeeld heeft het BasePoint type geen typediscriminator, terwijl het ThreeDimensionalPoint type een int typediscriminator heeft en het FourDimensionalPoint type een string typediscriminator heeft.

Belangrijk

Polymorfische serialisatie werkt alleen als het type geserialiseerde waarde dat van het polymorfe basistype is. Dit omvat het gebruik van het basistype als de algemene typeparameter bij het serialiseren van waarden op basisniveau, als het gedeclareerde type geserialiseerde eigenschappen of als het verzamelingselement in geserialiseerde verzamelingen.

using System.Text.Json;
using System.Text.Json.Serialization;

PerformRoundTrip<BasePoint>();
PerformRoundTrip<ThreeDimensionalPoint>();
PerformRoundTrip<FourDimensionalPoint>();

static void PerformRoundTrip<T>() where T : BasePoint, new()
{
    var json = JsonSerializer.Serialize<BasePoint>(new T());
    Console.WriteLine(json);

    BasePoint? result = JsonSerializer.Deserialize<BasePoint>(json);
    Console.WriteLine($"result is {typeof(T)}; // {result is T}");
    Console.WriteLine();
}
// Sample output:
//   { "X": 541, "Y": 503 }
//   result is BasePoint; // True
//
//   { "$type": 3, "Z": 399, "X": 835, "Y": 78 }
//   result is ThreeDimensionalPoint; // True
//
//   { "$type": "4d", "W": 993, "Z": 427, "X": 508, "Y": 741 }
//   result is FourDimensionalPoint; // True
Imports System.Text.Json
Imports System.Text.Json.Serialization

Module Program
    Sub Main()
        PerformRoundTrip(Of BasePoint)()
        PerformRoundTrip(Of ThreeDimensionalPoint)()
        PerformRoundTrip(Of FourDimensionalPoint)()
    End Sub

    Private Sub PerformRoundTrip(Of T As {BasePoint, New})()
        Dim json = JsonSerializer.Serialize(Of BasePoint)(New T())
        Console.WriteLine(json)

        Dim result As BasePoint = JsonSerializer.Deserialize(Of BasePoint)(json)
        Console.WriteLine($"result is {GetType(T)}; // {TypeOf result Is T}")
        Console.WriteLine()
    End Sub
End Module
' Sample output:
'   { "X": 649, "Y": 754 }
'   result is BasePoint; // True
'
'   { "$type": 3, "Z": 247, "X": 814, "Y": 56 }
'   result is ThreeDimensionalPoint; // True
'
'   { "$type": "4d", "W": 427, "Z": 193, "X": 112, "Y": 935 }
'   result is FourDimensionalPoint; // True

De naam van de typediscriminator aanpassen

De standaardeigenschapsnaam voor het type discriminator is $type. Als u de naam van de eigenschap wilt aanpassen, gebruikt u de JsonPolymorphicAttribute naam zoals wordt weergegeven in het volgende voorbeeld:

[JsonPolymorphic(TypeDiscriminatorPropertyName = "$discriminator")]
[JsonDerivedType(typeof(ThreeDimensionalPoint), typeDiscriminator: "3d")]
public class BasePoint
{
    public int X { get; set; }
    public int Y { get; set; }
}

public sealed class ThreeDimensionalPoint : BasePoint
{
    public int Z { get; set; }
}
<JsonPolymorphic(TypeDiscriminatorPropertyName:="$discriminator")>
<JsonDerivedType(GetType(ThreeDimensionalPoint), "3d")>
Public Class BasePoint
    Public Property X As Integer
    Public Property Y As Integer
End Class

Public Class ThreeDimensionalPoint
    Inherits BasePoint
    Public Property Z As Integer
End Class

In de bovenstaande code configureert het attribuut JsonPolymorphic de TypeDiscriminatorPropertyName op de waarde "$discriminator". Wanneer de typediscriminatienaam is geconfigureerd, wordt in het volgende voorbeeld het ThreeDimensionalPoint type geserialiseerd als JSON weergegeven:

BasePoint point = new ThreeDimensionalPoint { X = 1, Y = 2, Z = 3 };
var json = JsonSerializer.Serialize<BasePoint>(point);
Console.WriteLine(json);
// Sample output:
//  { "$discriminator": "3d", "X": 1, "Y": 2, "Z": 3 }
Dim point As BasePoint = New ThreeDimensionalPoint With { .X = 1, .Y = 2, .Z = 3 }
Dim json As String = JsonSerializer.Serialize(Of BasePoint)(point)
Console.WriteLine(json)
' Sample output:
'  { "$discriminator": "3d", "X": 1, "Y": 2, "Z": 3 }

Tip

Vermijd het gebruik van een JsonPolymorphicAttribute.TypeDiscriminatorPropertyName eigenschap die conflicteert met een eigenschap in uw typehiërarchie.

Onbekende afgeleide typen verwerken

Als u onbekende afgeleide typen wilt verwerken, moet u zich aanmelden voor dergelijke ondersteuning met behulp van een aantekening op het basistype. Houd rekening met de volgende typehiërarchie:

[JsonDerivedType(typeof(ThreeDimensionalPoint))]
public class BasePoint
{
    public int X { get; set; }
    public int Y { get; set; }
}

public class ThreeDimensionalPoint : BasePoint
{
    public int Z { get; set; }
}

public class FourDimensionalPoint : ThreeDimensionalPoint
{
    public int W { get; set; }
}
<JsonDerivedType(GetType(ThreeDimensionalPoint))>
Public Class BasePoint
    Public Property X As Integer
    Public Property Y As Integer
End Class

Public Class ThreeDimensionalPoint
    Inherits BasePoint
    Public Property Z As Integer
End Class

Public NotInheritable Class FourDimensionalPoint
    Inherits ThreeDimensionalPoint
    Public Property W As Integer
End Class

Omdat de configuratie niet expliciet ondersteuning voor FourDimensionalPoint inschakelt, zullen pogingen door exemplaren van FourDimensionalPoint als BasePoint te serialiseren leiden tot een runtime-uitzondering.

JsonSerializer.Serialize<BasePoint>(new FourDimensionalPoint()); // throws NotSupportedException
JsonSerializer.Serialize(Of BasePoint)(New FourDimensionalPoint()) ' throws NotSupportedException

U kunt het standaardgedrag wijzigen met behulp van de JsonUnknownDerivedTypeHandling enum, die als volgt kan worden opgegeven:

[JsonPolymorphic(
    UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToBaseType)]
[JsonDerivedType(typeof(ThreeDimensionalPoint))]
public class BasePoint
{
    public int X { get; set; }
    public int Y { get; set; }
}

public class ThreeDimensionalPoint : BasePoint
{
    public int Z { get; set; }
}

public class FourDimensionalPoint : ThreeDimensionalPoint
{
    public int W { get; set; }
}
<JsonPolymorphic(
    UnknownDerivedTypeHandling:=JsonUnknownDerivedTypeHandling.FallBackToBaseType)>
<JsonDerivedType(GetType(ThreeDimensionalPoint))>
Public Class BasePoint
    Public Property X As Integer
    Public Property Y As Integer
End Class

Public Class ThreeDimensionalPoint
    Inherits BasePoint
    Public Property Z As Integer
End Class

Public NotInheritable Class FourDimensionalPoint
    Inherits ThreeDimensionalPoint
    Public Property W As Integer
End Class

In plaats van terug te vallen op het basistype, kunt u de FallBackToNearestAncestor instelling gebruiken om terug te vallen op het contract van het dichtstbijzijnde gedeclareerde afgeleide type:

[JsonPolymorphic(
    UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToNearestAncestor)]
[JsonDerivedType(typeof(BasePoint))]
public interface IPoint { }

public class BasePoint : IPoint { }

public class ThreeDimensionalPoint : BasePoint { }
<JsonPolymorphic(
    UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToNearestAncestor)>
<JsonDerivedType(GetType(BasePoint)>
Public Interface IPoint
End Interface

Public Class BasePoint
    Inherits IPoint
End Class

Public Class ThreeDimensionalPoint
    Inherits BasePoint
End Class

Met een configuratie zoals in het voorgaande voorbeeld wordt het ThreeDimensionalPoint type geserialiseerd als BasePoint:

// Serializes using the contract for BasePoint
JsonSerializer.Serialize<IPoint>(new ThreeDimensionalPoint());
' Serializes using the contract for BasePoint
JsonSerializer.Serialize(Of IPoint)(New ThreeDimensionalPoint())

Als u echter uitgaat van de dichtstbijzijnde voorouder, ontstaat de mogelijkheid van "diamant"-ambiguïteit. Bekijk de volgende typehiërarchie als voorbeeld:

[JsonPolymorphic(
    UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToNearestAncestor)]
[JsonDerivedType(typeof(BasePoint))]
[JsonDerivedType(typeof(IPointWithTimeSeries))]
public interface IPoint { }

public interface IPointWithTimeSeries : IPoint { }

public class BasePoint : IPoint { }

public class BasePointWithTimeSeries : BasePoint, IPointWithTimeSeries { }
<JsonPolymorphic(
    UnknownDerivedTypeHandling:=JsonUnknownDerivedTypeHandling.FallBackToNearestAncestor)>
<JsonDerivedType(GetType(BasePoint))>
<JsonDerivedType(GetType(IPointWithTimeSeries))>
Public Interface IPoint
End Interface

Public Interface IPointWithTimeSeries
    Inherits IPoint
End Interface

Public Class BasePoint
    Implements IPoint
End Class

Public Class BasePointWithTimeSeries
    Inherits BasePoint
    Implements IPointWithTimeSeries
End Class

In dit geval kan het type BasePointWithTimeSeries worden geserialiseerd als BasePoint of IPointWithTimeSeries, aangezien beide directe bovenliggende klassen zijn. Deze dubbelzinnigheid zorgt ervoor dat de fout NotSupportedException wordt gegenereerd wanneer wordt geprobeerd een instantie van BasePointWithTimeSeries als IPoint te serialiseren.

// throws NotSupportedException
JsonSerializer.Serialize<IPoint>(new BasePointWithTimeSeries());
' throws NotSupportedException
JsonSerializer.Serialize(Of IPoint)(New BasePointWithTimeSeries())

Polymorfisme afleiden uit een gesloten hiërarchie

Vanaf .NET 11 System.Text.Json kunnen afgeleide typen worden afgeleid van een gesloten C# 15-hiërarchie. Deductie op één hiërarchie inschakelen via JsonPolymorphicAttribute.InferClosedTypePolymorphism:

[JsonPolymorphic(InferClosedTypePolymorphism = true)]
public closed class Shape { }
public sealed class Circle : Shape { }
public sealed class Square : Shape { }

De serializer registreert elk afgeleid type en gebruikt de eenvoudige typenaam als een tekenreeksdiscriminatie. Bijvoorbeeld, een "$type":"Circle" payload bevat Circle.

Als u deductie wilt inschakelen voor elke gesloten hiërarchie die door een exemplaar van opties wordt verwerkt, stelt u JsonSerializerOptions.InferClosedTypePolymorphismhet volgende in:

var options = new JsonSerializerOptions
{
    InferClosedTypePolymorphism = true
};

Stel voor het genereren van de bron het volgende in JsonSourceGenerationOptionsAttribute.InferClosedTypePolymorphism:

[JsonSourceGenerationOptions(InferClosedTypePolymorphism = true)]
[JsonSerializable(typeof(Shape))]
internal partial class AppJsonContext : JsonSerializerContext;

Stel deductie in voor het kenmerk brongeneratie wanneer u een gegenereerde context gebruikt. Alleen het inschakelen van de runtime-eigenschap JsonSerializerOptions kan geen metagegevens voor afgeleide typen toevoegen die de brongenerator niet heeft gegenereerd.

Het kenmerk op typeniveau heeft voorrang op de globale instelling. Stel InferClosedTypePolymorphism = false in op JsonPolymorphicAttribute om één hiërarchie uit te sluiten van een globale instelling.

Expliciete JsonDerivedTypeAttribute-registraties vervangen afleiding voor die hiërarchie. Ze breiden de afgeleide lijst niet uit. Het toepassen van InferClosedTypePolymorphism = true op een type dat geen closed is, veroorzaakt een InvalidOperationException bij serialisatie op basis van reflectie en leidt tot een fout bij brongeneratie. Uitgestelde typen met dubbele eenvoudige namen produceren discriminatorconflicten en elk uitgestelde type moet ten minste zo toegankelijk zijn als de gesloten basis.

Open generieke afgeleide typen configureren

Vanaf .NET 11 accepteert JsonDerivedTypeAttribute een open generiek afgeleid type wanneer de serialisatiefunctie een uniek gesloten type kan afleiden uit het geserialiseerde basistype:

[JsonDerivedType(typeof(Derived<>), "derived")]
public class Base<T>;
public class Derived<T> : Base<T>;
<JsonDerivedType(GetType(Derived(Of )), "derived")>
Public Class Base(Of T)
End Class
Public Class Derived(Of T)
    Inherits Base(Of T)
End Class

Voor Base<int>, de serializer registreert Derived<int>. Dezelfde resolutie ondersteunt algemene interfaces, opnieuw gerangschikte typeparameters, geneste algemene argumenten, matrices en afgeleide typen waarmee sommige basistypeargumenten worden hersteld naar concrete typen.

Elke afgeleide typeparameter moet worden afgeleid van het gesloten basistype, de vervanging moet ondubbelzinnig zijn en het resulterende type moet voldoen aan de algemene beperkingen. Serialisatie op basis van weerspiegeling genereert InvalidOperationException voor een niet-ondersteunde specialisatie. Brongeneratie meldt SYSLIB1229, en de gegenereerde hiërarchie faalt nog steeds wanneer de serialisator haar configureert. Als u de waarschuwing onderdrukt, wordt de registratie niet geldig.

Polymorfisme configureren met het contractmodel

Voor gebruiksvoorbeelden waarbij kenmerkaantekeningen onpraktisch of onmogelijk zijn (zoals grote domeinmodellen, cross-assemblyhiërarchieën of hiërarchieën in afhankelijkheden van derden), gebruikt u het contractmodel om polymorfisme te configureren. Het contractmodel is een set API's die kunnen worden gebruikt om polymorfisme in een typehiërarchie te configureren door een aangepaste DefaultJsonTypeInfoResolver subklasse te maken die dynamisch polymorf configuratie per type biedt, zoals wordt weergegeven in het volgende voorbeeld:

public class PolymorphicTypeResolver : DefaultJsonTypeInfoResolver
{
    public override JsonTypeInfo GetTypeInfo(Type type, JsonSerializerOptions options)
    {
        JsonTypeInfo jsonTypeInfo = base.GetTypeInfo(type, options);

        Type basePointType = typeof(BasePoint);
        if (jsonTypeInfo.Type == basePointType)
        {
            jsonTypeInfo.PolymorphismOptions = new JsonPolymorphismOptions
            {
                TypeDiscriminatorPropertyName = "$point-type",
                IgnoreUnrecognizedTypeDiscriminators = true,
                UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FailSerialization,
                DerivedTypes =
                {
                    new JsonDerivedType(typeof(ThreeDimensionalPoint), "3d"),
                    new JsonDerivedType(typeof(FourDimensionalPoint), "4d")
                }
            };
        }

        return jsonTypeInfo;
    }
}
Public Class PolymorphicTypeResolver
    Inherits DefaultJsonTypeInfoResolver

    Public Overrides Function GetTypeInfo(
        ByVal type As Type,
        ByVal options As JsonSerializerOptions) As JsonTypeInfo

        Dim jsonTypeInfo As JsonTypeInfo = MyBase.GetTypeInfo(type, options)
        Dim basePointType As Type = GetType(BasePoint)

        If jsonTypeInfo.Type = basePointType Then
            jsonTypeInfo.PolymorphismOptions = New JsonPolymorphismOptions With {
                .TypeDiscriminatorPropertyName = "$point-type",
                .IgnoreUnrecognizedTypeDiscriminators = True,
                .UnknownDerivedTypeHandling =
                    JsonUnknownDerivedTypeHandling.FailSerialization
            }
            jsonTypeInfo.PolymorphismOptions.DerivedTypes.Add(
                New JsonDerivedType(GetType(ThreeDimensionalPoint), "3d"))
            jsonTypeInfo.PolymorphismOptions.DerivedTypes.Add(
                New JsonDerivedType(GetType(FourDimensionalPoint), "4d"))
        End If

        Return jsonTypeInfo
    End Function
End Class

Aanvullende polymorfe serialisatiedetails

  • Polymorfische serialisatie ondersteunt afgeleide typen die expliciet zijn aangemeld via de JsonDerivedTypeAttribute. Niet-declaratieve typen resulteren in een runtime-uitzondering. Het gedrag kan worden gewijzigd door de JsonPolymorphicAttribute.UnknownDerivedTypeHandling eigenschap te configureren.
  • Polymorfe configuratie die is opgegeven in afgeleide typen wordt niet overgenomen door polymorfe configuratie in basistypen. Het basistype moet onafhankelijk worden geconfigureerd.
  • Polymorfische hiërarchieën worden ondersteund voor beide interface en class typen.
  • Polymorfisme met behulp van typediscriminatoren wordt alleen ondersteund voor typehiërarchieën die gebruikmaken van de standaardconversieprogramma's voor objecten, verzamelingen en woordenlijsttypen.
  • Polymorfisme wordt ondersteund in brongeneratie op basis van metagegevens, maar niet in fast-path-brongeneratie.

Zie ook