Lingua
Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
In questo articolo viene illustrato come serializzare le proprietà delle classi derivate con il namespace System.Text.Json.
Serializzare le proprietà delle classi derivate
A partire da .NET 7, System.Text.Json supporta la serializzazione e la deserializzazione della gerarchia di tipi polimorfici con annotazioni degli attributi.
| Attributo | Descrizione |
|---|---|
| JsonDerivedTypeAttribute | Se posizionato su una dichiarazione di tipo, indica che il sottotipo specificato deve essere scelto per la serializzazione polimorfica. Espone anche la possibilità di specificare un discriminatore di tipo. |
| JsonPolymorphicAttribute | Se inserito in una dichiarazione di tipo, indica che il tipo deve essere serializzato in modo polimorfico. Espone anche varie opzioni per configurare la serializzazione e la deserializzazione polimorfica per tale tipo. |
Si supponga, ad esempio, di avere una classe WeatherForecastBase e una classe derivata WeatherForecastWithCity:
[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
Si supponga che l'argomento tipo del metodo Serialize<TValue> in fase di compilazione sia WeatherForecastBase:
options = new JsonSerializerOptions
{
WriteIndented = true
};
jsonString = JsonSerializer.Serialize<WeatherForecastBase>(weatherForecastBase, options);
options = New JsonSerializerOptions With {
.WriteIndented = True
}
jsonString = JsonSerializer.Serialize(WeatherForecastBase, options)
In questo scenario, la proprietà City viene serializzata perché l'oggetto weatherForecastBase è effettivamente un oggetto WeatherForecastWithCity. Questa configurazione abilita la serializzazione polimorfica per WeatherForecastBase, in particolare quando il tipo di runtime è WeatherForecastWithCity:
{
"City": "Milwaukee",
"Date": "2022-09-26T00:00:00-05:00",
"TemperatureCelsius": 15,
"Summary": "Cool"
}
Anche se il processo di andata e ritorno del payload WeatherForecastBase è supportato, non si concretizzerà come un tipo di runtime di WeatherForecastWithCity. Si materializzerà invece come tipo di runtime di 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
La sezione seguente descrive come aggiungere metadati per abilitare l'andata e ritorno del tipo derivato.
Discriminanti di tipi polimorfici
Per abilitare la deserializzazione polimorfica, è necessario specificare un discriminatore di tipo per la classe derivata:
[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
Con i metadati aggiunti, in particolare il discriminatore di tipo, il serializzatore può serializzare e deserializzare il payload come tipo WeatherForecastWithCity dal suo tipo di base WeatherForecastBase. La serializzazione genera JSON insieme ai metadati discriminatori del tipo:
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"
' }
Con il discriminante di tipo, il serializzatore può deserializzare il payload in modo polimorfico come 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
Nota
Per impostazione predefinita, il $type discriminare deve essere posizionato all'inizio dell'oggetto JSON, raggruppato con altre proprietà di metadati come $id e $ref. Se leggi dati da un'API esterna che posiziona il discriminatore $type al centro dell'oggetto JSON, imposta JsonSerializerOptions.AllowOutOfOrderMetadataProperties su true:
JsonSerializerOptions options = new() { AllowOutOfOrderMetadataProperties = true };
JsonSerializer.Deserialize<Base>("""{"Name":"Name","$type":"derived"}""", options);
Fare attenzione quando si attiva questo flag, poiché potrebbe causare un buffering eccessivo (e errori di memoria esaurita) durante la deserializzazione in streaming di oggetti JSON molto grandi.
Combinare i formati dei discriminatori di tipo
Gli identificatori del discriminatore di tipo sono validi nei moduli string o int, pertanto è valido quanto segue:
[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...
' }
Sebbene l'API supporti la combinazione di diverse configurazioni del discriminatore di tipo, non è consigliato. La raccomandazione generale è di usare o tutti i discriminatori di tipo string, o tutti i discriminatori di tipo int, oppure nessun discriminatore. L'esempio seguente mostra come combinare e associare le configurazioni dei discriminatori di tipo:
[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
Nell'esempio precedente, il tipo BasePoint non dispone di un discriminante di tipo, mentre il tipo ThreeDimensionalPoint ha un discriminante di tipo int e FourDimensionalPoint ha un discriminante di tipo string.
Importante
Per il funzionamento della serializzazione polimorfica, il tipo del valore serializzato deve essere quello del tipo di base polimorfico. Ciò include l'uso del tipo di base come parametro di tipo generico durante la serializzazione dei valori a livello radice, come tipo dichiarato di proprietà serializzate o come elemento della raccolta nelle raccolte serializzate.
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
Personalizzare il nome del discriminatore di tipo
Il nome predefinito della proprietà per il discriminatore di tipo è $type. Per personalizzare il nome della proprietà, usare JsonPolymorphicAttribute come mostrato nell'esempio seguente:
[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
Nel codice precedente, l'attributo JsonPolymorphic configura TypeDiscriminatorPropertyName sul valore "$discriminator". Con il nome del discriminatore di tipo configurato, l'esempio seguente mostra il tipo ThreeDimensionalPoint serializzato come JSON:
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 }
Suggerimento
Evitare di usare un JsonPolymorphicAttribute.TypeDiscriminatorPropertyName in conflitto con una proprietà nella gerarchia dei tipi.
Gestire i tipi derivati sconosciuti
Per gestire i tipi derivati sconosciuti, è necessario acconsentire esplicitamente al loro supporto con un'annotazione sul tipo di base. Si consideri la gerarchia di tipi seguente:
[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
Poiché la configurazione non supporta esplicitamente il supporto per FourDimensionalPoint, il tentativo di serializzare le istanze di FourDimensionalPoint come BasePoint comporterà un'eccezione di runtime:
JsonSerializer.Serialize<BasePoint>(new FourDimensionalPoint()); // throws NotSupportedException
JsonSerializer.Serialize(Of BasePoint)(New FourDimensionalPoint()) ' throws NotSupportedException
È possibile modificare il comportamento predefinito usando l'enumerazione JsonUnknownDerivedTypeHandling, che può essere specificata nel modo seguente:
[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
Anziché eseguire il fallback al tipo di base, è possibile usare l'impostazione FallBackToNearestAncestor per eseguire il fallback al contratto del tipo derivato dichiarato più vicino:
[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
Con una configurazione come quella dell'esempio precedente, il tipo ThreeDimensionalPoint verrà serializzato come BasePoint:
// Serializes using the contract for BasePoint
JsonSerializer.Serialize<IPoint>(new ThreeDimensionalPoint());
' Serializes using the contract for BasePoint
JsonSerializer.Serialize(Of IPoint)(New ThreeDimensionalPoint())
Tuttavia, il fallback al predecessore più vicino ammette la possibilità di ambiguità "diamante". Si consideri la seguente gerarchia di tipi come esempio:
[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 questo caso, il tipo BasePointWithTimeSeries può essere serializzato come BasePoint o IPointWithTimeSeries poiché sono entrambi predecessori diretti. Questa ambiguità farà sì che venga generato NotSupportedException quando si tenta di serializzare un'istanza di BasePointWithTimeSeries come IPoint.
// throws NotSupportedException
JsonSerializer.Serialize<IPoint>(new BasePointWithTimeSeries());
' throws NotSupportedException
JsonSerializer.Serialize(Of IPoint)(New BasePointWithTimeSeries())
Dedurre il polimorfismo da una gerarchia chiusa
A partire da .NET 11, System.Text.Json è possibile dedurre i tipi derivati da una gerarchia chiusa C# 15. Abilita l'inferenza su una gerarchia tramite JsonPolymorphicAttribute.InferClosedTypePolymorphism:
[JsonPolymorphic(InferClosedTypePolymorphism = true)]
public closed class Shape { }
public sealed class Circle : Shape { }
public sealed class Square : Shape { }
Il serializzatore registra ogni tipo derivato e usa il nome del tipo semplice come discriminante di stringa. Ad esempio, un Circle payload contiene "$type":"Circle".
Per abilitare l'inferenza per ogni gerarchia chiusa gestita da un'istanza di opzioni, impostare JsonSerializerOptions.InferClosedTypePolymorphism:
var options = new JsonSerializerOptions
{
InferClosedTypePolymorphism = true
};
Per la generazione del codice sorgente, impostare JsonSourceGenerationOptionsAttribute.InferClosedTypePolymorphism:
[JsonSourceGenerationOptions(InferClosedTypePolymorphism = true)]
[JsonSerializable(typeof(Shape))]
internal partial class AppJsonContext : JsonSerializerContext;
Impostare l'inferenza per l'attributo di generazione del codice sorgente quando si utilizza un contesto generato. L'abilitazione solo della proprietà di runtime JsonSerializerOptions non può aggiungere metadati di tipo derivato che il generatore di origine non ha generato.
L'attributo a livello di tipo ha la precedenza sull'impostazione globale. Impostare InferClosedTypePolymorphism = false su JsonPolymorphicAttribute per escludere una gerarchia da un'impostazione globale.
Le registrazioni esplicite JsonDerivedTypeAttribute sostituiscono l'inferenza per tale gerarchia. Non estendono l'elenco dedotto. L'applicazione di InferClosedTypePolymorphism = true a un tipo che non è closed genera un'eccezione InvalidOperationException con la serializzazione basata sulla reflection e produce un errore di generazione del codice sorgente. I tipi dedotti con nomi semplici duplicati producono collisioni discriminatorie e ogni tipo dedotto deve essere almeno accessibile come la base chiusa.
Configurare tipi derivati generici aperti
A partire da .NET 11, JsonDerivedTypeAttribute accetta un tipo derivato generico aperto quando il serializzatore può risolvere un tipo chiuso univoco dal tipo di base serializzato:
[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
Per Base<int>, il serializzatore registra Derived<int>. La stessa risoluzione supporta interfacce generiche, parametri di tipo riordinati, argomenti generici annidati, matrici e tipi derivati che fissano alcuni argomenti di tipo di base a tipi concreti.
Ogni parametro di tipo derivato deve essere inferibile dal tipo di base chiuso, la sostituzione deve essere ambigua e il tipo risultante deve soddisfare i vincoli generici. La serializzazione basata sulla riflessione genera InvalidOperationException per una specializzazione non supportata. La generazione del codice sorgente segnala SYSLIB1229 e la gerarchia generata continua comunque a non funzionare quando viene configurata dal serializzatore. L'eliminazione dell'avviso non rende valida la registrazione.
Configurare il polimorfismo con il modello di contratto
Per i casi d'uso in cui le annotazioni degli attributi sono poco pratiche o impossibili (ad esempio modelli di dominio di grandi dimensioni, gerarchie tra assembly o gerarchie nelle dipendenze di terze parti), per configurare il polimorfismo usare il modello di contratto. Il modello di contratto è un set di API che possono essere usate per configurare il polimorfismo in una gerarchia di tipi creando una sottoclasse personalizzata DefaultJsonTypeInfoResolver che fornisce dinamicamente una configurazione polimorfica per tipo, come illustrato nell'esempio seguente:
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
Dettagli aggiuntivi sulla serializzazione polimorfica
- La serializzazione polimorfica supporta i tipi derivati esplicitamente inclusi tramite JsonDerivedTypeAttribute. I tipi non dichiarati genereranno un'eccezione di runtime. Il comportamento può essere modificato configurando la proprietà JsonPolymorphicAttribute.UnknownDerivedTypeHandling.
- La configurazione polimorfica specificata nei tipi derivati non viene ereditata dalla configurazione polimorfica nei tipi di base. Il tipo di base deve essere configurato in modo indipendente.
- Le gerarchie polimorfiche sono supportate sia per
interfaceche per i tipiclass. - Il polimorfismo che usa i discriminatori dei tipi è supportato solo per le gerarchie di tipi che usano i convertitori predefiniti per oggetti, raccolte e tipi di dizionario.
- Il polimorfismo è supportato nella generazione di origine basata su metadati, ma non nella generazione di origini fast-path.