Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Из этой статьи вы узнаете, как сериализовать свойства производных классов с помощью пространства имен System.Text.Json.
Сериализация свойств производных классов
Начиная с .NET 7, System.Text.Json поддерживает сериализацию и десериализацию полиморфной иерархии типов с использованием атрибутов.
| Атрибут | Описание |
|---|---|
| JsonDerivedTypeAttribute | Если атрибут указан в объявлении типа, это означает, что указанный подтип участвует в полиморфной сериализации. Он также предоставляет возможность задать дискриминатор типа. |
| JsonPolymorphicAttribute | Если применяется к объявлению типа, указывает, что тип следует сериализовать полиморфно. Он также предоставляет различные параметры для настройки полиморфной сериализации и десериализации для этого типа. |
Например, предположим, что у вас есть класс WeatherForecastBase и производный класс 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
И предположим, что аргумент типа метода Serialize<TValue> на этапе компиляции равен WeatherForecastBase:
options = new JsonSerializerOptions
{
WriteIndented = true
};
jsonString = JsonSerializer.Serialize<WeatherForecastBase>(weatherForecastBase, options);
options = New JsonSerializerOptions With {
.WriteIndented = True
}
jsonString = JsonSerializer.Serialize(WeatherForecastBase, options)
В этом сценарии свойство City сериализуется, поскольку объект weatherForecastBase на самом деле является объектом WeatherForecastWithCity. Эта конфигурация включает полиморфную сериализацию для WeatherForecastBase, в частности, когда типом времени выполнения является WeatherForecastWithCity:
{
"City": "Milwaukee",
"Date": "2022-09-26T00:00:00-05:00",
"TemperatureCelsius": 15,
"Summary": "Cool"
}
Хотя обратная передача полезных данных поддерживается WeatherForecastBase, он не будет материализоваться как тип WeatherForecastWithCity среды выполнения. Вместо этого он будет материализоваться как тип среды выполнения 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
В следующем разделе описывается, как добавить метаданные для включения кругового обхода производного типа.
Дискриминаторы полиморфных типов
Чтобы включить полиморфную десериализацию, необходимо указать дискриминатор типа для производного класса:
[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
С добавленными метаданными, а именно дискриминатором типа, сериализатор может сериализовать и десериализовать данные как тип WeatherForecastWithCity на основе его базового типа WeatherForecastBase. Сериализация выводит JSON вместе с метаданными дискриминатора типа:
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"
' }
С помощью дискриминатора типа сериализатор может полиморфно десериализовать полезную нагрузку как 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
Примечание.
По умолчанию дискриминатор $type должен размещаться в начале объекта JSON вместе с другими свойствами метаданных, такими как $id и $ref. Если вы получаете данные из внешнего API, который размещает дискриминатор $type в середине объекта JSON, установите для JsonSerializerOptions.AllowOutOfOrderMetadataProperties значение true:
JsonSerializerOptions options = new() { AllowOutOfOrderMetadataProperties = true };
JsonSerializer.Deserialize<Base>("""{"Name":"Name","$type":"derived"}""", options);
Будьте осторожны при включении этого флага, так как это может привести к избыточной буферизации (и ошибкам из-за нехватки памяти) при потоковой десериализации очень больших объектов JSON.
Комбинирование форматов дискриминатора типа
Идентификаторы дискриминатора типа допустимы либо в форме string, либо в форме int, поэтому допустим следующий вариант:
[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...
' }
Хотя API поддерживает комбинирование различных конфигураций дискриминатора типов, делать это не рекомендуется. Общая рекомендация заключается в том, чтобы использовать либо только дискриминаторы типа string, либо только дискриминаторы типа int, либо вообще не использовать дискриминаторы. В следующем примере показано, как комбинировать различные конфигурации дискриминаторов типов.
[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
В предыдущем примере тип BasePoint не имеет дискриминатора типа, тогда как тип ThreeDimensionalPoint имеет дискриминатор типа int, а тип FourDimensionalPoint — дискриминатор типа string.
Внимание
Чтобы полиморфная сериализация работала, тип сериализуемого значения должен совпадать с полиморфным базовым типом. Это включает использование базового типа в качестве параметра универсального типа при сериализации значений корневого уровня в качестве объявленного типа сериализованных свойств или в качестве элемента коллекции в сериализованных коллекциях.
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
Настроить имя дискриминатора типа
Имя свойства по умолчанию для дискриминатора типа — $type. Чтобы настроить имя свойства, используйте JsonPolymorphicAttribute приведенный ниже пример:
[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
В предыдущем коде атрибут JsonPolymorphic задает для TypeDiscriminatorPropertyName значение "$discriminator". При настройке имени дискриминационных типов в следующем примере показан ThreeDimensionalPoint тип, сериализованный как 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 }
Совет
Избегайте использования JsonPolymorphicAttribute.TypeDiscriminatorPropertyName, конфликтующего со свойством в иерархии типов.
Обрабатывать неизвестные производные типы
Чтобы обрабатывать неизвестные производные типы, необходимо отказаться от такой поддержки с помощью заметки на базовом типе. Рассмотрим следующую иерархию типов:
[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
Поскольку конфигурация не предусматривает поддержку FourDimensionalPoint, попытка сериализовать экземпляры FourDimensionalPoint как BasePoint приведет к ошибке выполнения.
JsonSerializer.Serialize<BasePoint>(new FourDimensionalPoint()); // throws NotSupportedException
JsonSerializer.Serialize(Of BasePoint)(New FourDimensionalPoint()) ' throws NotSupportedException
Поведение по умолчанию можно изменить с помощью перечисления JsonUnknownDerivedTypeHandling, которое можно задать следующим образом:
[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
Вместо возврата к базовому типу можно использовать FallBackToNearestAncestor параметр для возврата к контракту ближайшего объявленного производного типа:
[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
При использовании конфигурации, аналогичной приведенному выше, ThreeDimensionalPoint тип будет сериализован как BasePoint:
// Serializes using the contract for BasePoint
JsonSerializer.Serialize<IPoint>(new ThreeDimensionalPoint());
' Serializes using the contract for BasePoint
JsonSerializer.Serialize(Of IPoint)(New ThreeDimensionalPoint())
Однако возврат к ближайшему предку допускает возможность неоднозначности «ромба». Рассмотрим следующую иерархию типов в качестве примера:
[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
В этом случае тип BasePointWithTimeSeries может быть сериализован как BasePoint, либо как IPointWithTimeSeries, поскольку оба являются его прямыми предками. Эта неоднозначность приведет к созданию исключения NotSupportedException при попытке сериализовать экземпляр BasePointWithTimeSeries как IPoint.
// throws NotSupportedException
JsonSerializer.Serialize<IPoint>(new BasePointWithTimeSeries());
' throws NotSupportedException
JsonSerializer.Serialize(Of IPoint)(New BasePointWithTimeSeries())
Вывод полиморфизма из закрытой иерархии
Начиная с .NET 11, System.Text.Json можно выводить производные типы из закрытой иерархии C# 15. Включите вывод для одной иерархии с помощью JsonPolymorphicAttribute.InferClosedTypePolymorphism:
[JsonPolymorphic(InferClosedTypePolymorphism = true)]
public closed class Shape { }
public sealed class Circle : Shape { }
public sealed class Square : Shape { }
Сериализатор регистрирует все производные типы и использует их простые имена типов в качестве строковых дискриминаторов. Например, Circle полезная нагрузка содержит "$type":"Circle".
Чтобы включить логический вывод для каждой закрытой иерархии, обрабатываемой экземпляром класса параметров, задайте JsonSerializerOptions.InferClosedTypePolymorphism:
var options = new JsonSerializerOptions
{
InferClosedTypePolymorphism = true
};
Для создания источника задайте JsonSourceGenerationOptionsAttribute.InferClosedTypePolymorphism:
[JsonSourceGenerationOptions(InferClosedTypePolymorphism = true)]
[JsonSerializable(typeof(Shape))]
internal partial class AppJsonContext : JsonSerializerContext;
Настройте вывод для атрибута генерации исходного кода при использовании сгенерированного контекста. Включение только свойства времени выполнения JsonSerializerOptions не позволяет добавить метаданные о производных типах, которые генератор исходного кода не сгенерировал.
Атрибут уровня типа имеет приоритет над глобальным параметром. Установите InferClosedTypePolymorphism = false для JsonPolymorphicAttribute, чтобы исключить одну иерархию из действия глобального параметра.
Явные JsonDerivedTypeAttribute регистрации заменяют вывод для этой иерархии. Они не расширяют выводимый список. Применение InferClosedTypePolymorphism = true к типу, который не является closed, вызывает исключение InvalidOperationException при сериализации на основе отражения и приводит к ошибке при генерации исходного кода. Выводимые типы с повторяющимися простыми именами создают дискриминационные столкновения, и каждый выводенный тип должен быть по крайней мере так же доступен, как закрытая база.
Настройка открытых универсальных производных типов
Начиная с .NET 11, JsonDerivedTypeAttribute принимает открытый производный универсальный тип, если сериализатор может определить конкретный закрытый тип по сериализованному базовому типу:
[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
Для Base<int>, сериализатор регистрирует Derived<int>. То же разрешение поддерживает универсальные интерфейсы, параметры переупорядоченного типа, вложенные универсальные аргументы, массивы и производные типы, которые исправляют некоторые аргументы базового типа для конкретных типов.
Каждый параметр производного типа должен быть выведен из закрытого базового типа, подстановка должна быть однозначной, и результирующий тип должен соответствовать его универсальным ограничениям. Сериализация на основе рефлексии вызывает исключение InvalidOperationException для неподдерживаемой специализации. Генерация исходного кода сообщает о SYSLIB1229, и сгенерированная иерархия по-прежнему приводит к сбою, когда сериализатор ее настраивает. Отключение предупреждения не делает регистрацию допустимой.
Настройка полиморфизма с помощью модели контракта
В случаях, когда аннотации атрибутов непрактичны или невозможны (например, в больших моделях предметной области, межсборочных иерархиях или иерархиях в сторонних зависимостях), для настройки полиморфизма используйте contract model. Модель контракта — это набор API, которые можно использовать для настройки полиморфизма в иерархии типов путем создания настраиваемого DefaultJsonTypeInfoResolver подкласса, который динамически предоставляет полиморфную конфигурацию для каждого типа, как показано в следующем примере:
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
Дополнительные сведения о полиморфной сериализации
- Полиморфная сериализация поддерживает производные типы, которые были явно включены с помощью JsonDerivedTypeAttribute. Необъявленные типы приводят к исключению среды выполнения. Поведение можно изменить, настроив JsonPolymorphicAttribute.UnknownDerivedTypeHandling свойство.
- Полиморфная конфигурация, указанная в производных типах, не наследуется полиморфной конфигурацией в базовых типах. Базовый тип должен быть настроен независимо.
- Полиморфные иерархии поддерживаются для обоих
interfaceclassтипов. - Полиморфизм, использующий дискриминационные типы, поддерживается только для иерархий типов, использующих преобразователи по умолчанию для объектов, коллекций и типов словарей.
- Полиморфизм поддерживается при генерации кода на основе метаданных, но не при быстрой генерации кода.