jsonConverterSourceGenerator by Aviationexam
Nuget / site data
Details
Info
Name: jsonConverterSourceGenerator
Package Description
Author: Aviationexam
NuGet: https://www.nuget.org/packages/Aviationexam.GeneratedJsonConverters.SourceGenerator/
You can find more details at https://github.com/aviationexam/json-converter-source-generator
Source : https://github.com/aviationexam/json-converter-source-generator
Original Readme
Aviationexam.GeneratedJsonConverters.SourceGenerator
Motivation for this library are polymorphic contracts with discriminator property not present as first property.
i.e. this JSON
{
"baseProperty": 1,
"$type": 2,
"anotherLeafProperty": 2
}
is deserialized correctly into AnotherLeafContract
using this library.
And string based enum serialization.
Install
<ItemGroup>
<PackageReference Include="Aviationexam.GeneratedJsonConverters.SourceGenerator" Version="0.1.0" PrivateAssets="all" />
</ItemGroup>
How to use library
<PropertyGroup>
<!-- DefaultJsonSerializerContext configuration is required to generate UseEnumConverters method -->
<AVI_EJC_DefaultJsonSerializerContext_ClassAccessibility>public</AVI_EJC_DefaultJsonSerializerContext_ClassAccessibility>
<AVI_EJC_DefaultJsonSerializerContext_Namespace>NamespaceOf.My.Json.Serializer.Context</AVI_EJC_DefaultJsonSerializerContext_Namespace>
<AVI_EJC_DefaultJsonSerializerContext_ClassName>MyJsonSerializerContext</AVI_EJC_DefaultJsonSerializerContext_ClassName>
<!-- Allowed options BackingType, FirstEnumName. Default value FirstEnumName -->
<AVI_EJC_DefaultEnumSerializationStrategy>BackingType</AVI_EJC_DefaultEnumSerializationStrategy>
<!-- Allowed options UseBackingType, UseEnumName, or UseBackingType|UseEnumName (DeserializationStrategy is Flags enum). Default value UseEnumName -->
<AVI_EJC_DefaultEnumDeserializationStrategy>UseBackingType|UseEnumName</AVI_EJC_DefaultEnumDeserializationStrategy>
</PropertyGroup>
// file=contracts.cs
using Aviationexam.GeneratedJsonConverters.Attributes;
[JsonPolymorphic] // notice, that attributes are from `Aviationexam.GeneratedJsonConverters.Attributes` namespace, not `System.Text.Json.Serialization`
[JsonDerivedType(typeof(LeafContract), typeDiscriminator: nameof(LeafContract))]
[JsonDerivedType(typeof(AnotherLeafContract), typeDiscriminator: 2)]
[JsonDerivedType<GenericLeafContract>(typeDiscriminator: nameof(GenericLeafContract))]
public abstract class BaseContract
{
public int BaseProperty { get; set; }
}
public sealed class LeafContract : BaseContract
{
public int LeafProperty { get; set; }
}
public sealed class AnotherLeafContract : BaseContract
{
public int AnotherLeafProperty { get; set; }
}
public sealed class GenericLeafContract : BaseContract
{
public int Property { get; set; }
}
[EnumJsonConverter] // this use project defined configuration
public enum EMyEnum
{
[EnumMember(Value = "C")]
A,
[EnumMember(Value = "D")]
B,
}
[EnumJsonConverter(
SerializationStrategy = EnumSerializationStrategy.FirstEnumName,
DeserializationStrategy = EnumDeserializationStrategy.UseEnumName
)]
public enum EMyEnumWithExplicitConfiguration
{
[EnumMember(Value = "C")]
A,
[EnumMember(Value = "D")]
B,
}
[DisableEnumJsonConverter]
public enum EMyIgnoredEnum
{
C,
D,
}
// file=MyJsonSerializerContext.cs
using System.Text.Json.Serialization;
[JsonSerializable(typeof(BaseContract))] // this line is neccesary, generator searches for JsonSerializableAttribute with argument type decorated by JsonPolymorphicAttribute
[JsonSerializable(typeof(LeafContract))] // notice, it's necessary to specify leaf types
[JsonSerializable(typeof(AnotherLeafContract))]
[JsonSerializable(typeof(GenericLeafContract))]
[JsonSerializable(typeof(EMyEnum))] // only necessary for not referenced enums from other contracts
[JsonSerializable(typeof(EMyEnumWithExplicitConfiguration))]
public partial class MyJsonSerializerContext : JsonSerializerContext
{
static MyJsonSerializerContext()
{
// register generated converters to options
UsePolymorphicConverters(s_defaultOptions.Converters);
UseEnumConverters(s_defaultOptions.Converters);
}
}
About
Json Polymorphic generator
How to use
Example ( source csproj, source files )
- CSharp Project
- Program.cs
- Person.cs
- ProjectJsonSerializerContext.cs
This is the CSharp Project that references jsonConverterSourceGenerator
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Aviationexam.GeneratedJsonConverters.SourceGenerator" Version="0.1.11" PrivateAssets="all" />
</ItemGroup>
<PropertyGroup>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath>
</PropertyGroup>
</Project>
This is the use of jsonConverterSourceGenerator in Program.cs
//https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/polymorphism?pivots=dotnet-7-0
using JsonPolymorphicGeneratorDemo;
using System.Text.Json;
Person[] persons = new Person[2];
persons[0] = new Student() { Name="Student Ignat"};
persons[1] = new Teacher() { Name = "Teacher Ignat" };
//JsonSerializerOptions opt = new ()
//{
// WriteIndented = true
//};
//var ser = JsonSerializer.Serialize(persons, opt);
var ser = JsonSerializer.Serialize(persons, ProjectJsonSerializerContext.Default.Options);
Console.WriteLine(ser);
var p = JsonSerializer.Deserialize<Person[]>(ser,ProjectJsonSerializerContext.Default.Options);
if(p != null)
foreach (var item in p)
{
Console.WriteLine(item.Data());
}
This is the use of jsonConverterSourceGenerator in Person.cs
namespace JsonPolymorphicGeneratorDemo;
[Aviationexam.GeneratedJsonConverters.Attributes.JsonPolymorphic]
[Aviationexam.GeneratedJsonConverters.Attributes.JsonDerivedType(typeof(Student))]
[Aviationexam.GeneratedJsonConverters.Attributes.JsonDerivedType(typeof(Teacher))]
public abstract partial class Person
{
public string? Name { get; set; }
public abstract string Data();
}
public class Teacher : Person
{
public override string Data()
{
return "Class Teacher:" + Name;
}
}
public class Student : Person
{
public override string Data()
{
return "Class Student:" + Name;
}
}
This is the use of jsonConverterSourceGenerator in ProjectJsonSerializerContext.cs
//https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/polymorphism?pivots=dotnet-7-0
using JsonPolymorphicGeneratorDemo;
using System.Text.Json.Serialization;
[JsonSourceGenerationOptions(
WriteIndented = true,
PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase,
GenerationMode = JsonSourceGenerationMode.Default
)]
[JsonSerializable(typeof(Person[]))]
[JsonSerializable(typeof(Person))]
[JsonSerializable(typeof(Student))]
[JsonSerializable(typeof(Teacher))]
public partial class ProjectJsonSerializerContext : JsonSerializerContext
{
static ProjectJsonSerializerContext()
{
foreach (var converter in GetPolymorphicConverters())
{
s_defaultOptions.Converters.Add(converter);
}
}
}
Generated Files
Those are taken from $(BaseIntermediateOutputPath)\GX
- Attributes.DisableEnumJsonConverterAttribute.g.cs
- EnumDeserializationStrategy.g.cs
- EnumJsonConverterAttribute.g.cs
- EnumJsonConvertor.g.cs
- EnumSerializationStrategy.g.cs
- DiscriminatorStruct.g.cs
- IDiscriminatorStruct.g.cs
- JsonDerivedTypeAttribute.g.cs
- JsonPolymorphicAttribute.g.cs
- PersonJsonPolymorphicConverter.g.cs
- PolymorphicJsonConvertor.g.cs
- ProjectJsonSerializerContext.g.cs
- ProjectJsonSerializerContext.g.cs
- ProjectJsonSerializerContext.GetJsonTypeInfo.g.cs
- ProjectJsonSerializerContext.Person.g.cs
- ProjectJsonSerializerContext.PersonArray.g.cs
- ProjectJsonSerializerContext.PropertyNames.g.cs
- ProjectJsonSerializerContext.String.g.cs
- ProjectJsonSerializerContext.Student.g.cs
- ProjectJsonSerializerContext.Teacher.g.cs
// ReSharper disable once CheckNamespace
namespace Aviationexam.GeneratedJsonConverters.Attributes;
/// <summary>
/// When placed on an enum, indicates that generator should not report missing <see cref="EnumJsonConverterAttribute" />
/// </summary>
[System.AttributeUsage(System.AttributeTargets.Enum, AllowMultiple = false, Inherited = false)]
internal sealed class DisableEnumJsonConverterAttribute : System.Text.Json.Serialization.JsonAttribute
{
}
// ReSharper disable once RedundantNullableDirective
#nullable enable
using Aviationexam.GeneratedJsonConverters.Attributes;
using System;
namespace Aviationexam.GeneratedJsonConverters;
[Flags]
[DisableEnumJsonConverter]
internal enum EnumDeserializationStrategy : byte
{
ProjectDefault = 0,
UseBackingType = 1 << 0,
UseEnumName = 1 << 1,
}
#nullable enable
namespace Aviationexam.GeneratedJsonConverters.Attributes;
/// <summary>
/// When placed on an enum, indicates that the type should be serialized using generated enum convertor.
/// </summary>
[System.AttributeUsage(System.AttributeTargets.Enum, AllowMultiple = false, Inherited = false)]
internal sealed class EnumJsonConverterAttribute : System.Text.Json.Serialization.JsonAttribute
{
/// <summary>
/// Configure serialization strategy
/// </summary>
public EnumSerializationStrategy SerializationStrategy { get; set; } = EnumSerializationStrategy.ProjectDefault;
/// <summary>
/// Configure deserialization strategy
/// </summary>
public EnumDeserializationStrategy DeserializationStrategy { get; set; } = EnumDeserializationStrategy.ProjectDefault;
}
// ReSharper disable once RedundantNullableDirective
#nullable enable
using System;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Aviationexam.GeneratedJsonConverters;
internal abstract class EnumJsonConvertor<T, TBackingType> : JsonConverter<T>
where T : struct, Enum
where TBackingType : struct
{
protected abstract TypeCode BackingTypeTypeCode { get; }
protected abstract EnumDeserializationStrategy DeserializationStrategy { get; }
protected abstract EnumSerializationStrategy SerializationStrategy { get; }
public abstract bool TryToEnum(ReadOnlySpan<byte> enumName, out T value);
public abstract bool TryToEnum(TBackingType numericValue, out T value);
public abstract TBackingType ToBackingType(T value);
public abstract ReadOnlySpan<byte> ToFirstEnumName(T value);
public override T Read(
ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options
)
{
if (
reader.TokenType is JsonTokenType.String
&& DeserializationStrategy.HasFlag(EnumDeserializationStrategy.UseEnumName)
)
{
var enumName = reader.ValueSpan;
if (TryToEnum(enumName, out var enumValue))
{
return enumValue;
}
var stringValue = Encoding.UTF8.GetString(enumName.ToArray());
throw new JsonException($"Undefined mapping of '{stringValue}' to enum '{typeof(T).FullName}'");
}
if (reader.TokenType is JsonTokenType.Number)
{
var numericValue = ReadAsNumber(ref reader);
if (numericValue.HasValue)
{
if (TryToEnum(numericValue.Value, out var enumValue))
{
return enumValue;
}
throw new JsonException($"Undefined mapping of '{numericValue}' to enum '{{enumFullName}}'");
}
}
var value = Encoding.UTF8.GetString(reader.ValueSpan.ToArray());
throw new JsonException($"Unable to deserialize {value}('{reader.TokenType}') into {typeof(T).Name}");
}
public override T ReadAsPropertyName(
ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options
)
{
if (
reader.TokenType is JsonTokenType.PropertyName
&& DeserializationStrategy.HasFlag(EnumDeserializationStrategy.UseEnumName)
)
{
var enumName = reader.ValueSpan;
if (TryToEnum(enumName, out var enumValue))
{
return enumValue;
}
}
var value = Encoding.UTF8.GetString(reader.ValueSpan.ToArray());
if (
reader.TokenType is JsonTokenType.PropertyName
&& DeserializationStrategy.HasFlag(EnumDeserializationStrategy.UseBackingType)
)
{
var numericValue = ParseAsNumber(value);
if (numericValue.HasValue)
{
if (TryToEnum(numericValue.Value, out var enumValue))
{
return enumValue;
}
}
}
throw new JsonException($"Unable to deserialize {value}('{reader.TokenType}') into {typeof(T).Name}");
}
private TBackingType? ReadAsNumber(ref Utf8JsonReader reader) => BackingTypeTypeCode switch
{
TypeCode.SByte => reader.GetSByte() is var numericValue ? Unsafe.As<sbyte, TBackingType>(ref numericValue) : null,
TypeCode.Byte => reader.GetByte() is var numericValue ? Unsafe.As<byte, TBackingType>(ref numericValue) : null,
TypeCode.Int16 => reader.GetInt16() is var numericValue ? Unsafe.As<short, TBackingType>(ref numericValue) : null,
TypeCode.UInt16 => reader.GetUInt16() is var numericValue ? Unsafe.As<ushort, TBackingType>(ref numericValue) : null,
TypeCode.Int32 => reader.GetInt32() is var numericValue ? Unsafe.As<int, TBackingType>(ref numericValue) : null,
TypeCode.UInt32 => reader.GetUInt32() is var numericValue ? Unsafe.As<uint, TBackingType>(ref numericValue) : null,
TypeCode.Int64 => reader.GetInt64() is var numericValue ? Unsafe.As<long, TBackingType>(ref numericValue) : null,
TypeCode.UInt64 => reader.GetUInt64() is var numericValue ? Unsafe.As<ulong, TBackingType>(ref numericValue) : null,
_ => throw new ArgumentOutOfRangeException(nameof(BackingTypeTypeCode), BackingTypeTypeCode, $"Unexpected TypeCode {BackingTypeTypeCode}")
};
private TBackingType? ParseAsNumber(
string value
) => BackingTypeTypeCode switch
{
TypeCode.SByte => sbyte.TryParse(value, out var numericValue) ? Unsafe.As<sbyte, TBackingType>(ref numericValue) : null,
TypeCode.Byte => byte.TryParse(value, out var numericValue) ? Unsafe.As<byte, TBackingType>(ref numericValue) : null,
TypeCode.Int16 => short.TryParse(value, out var numericValue) ? Unsafe.As<short, TBackingType>(ref numericValue) : null,
TypeCode.UInt16 => ushort.TryParse(value, out var numericValue) ? Unsafe.As<ushort, TBackingType>(ref numericValue) : null,
TypeCode.Int32 => int.TryParse(value, out var numericValue) ? Unsafe.As<int, TBackingType>(ref numericValue) : null,
TypeCode.UInt32 => uint.TryParse(value, out var numericValue) ? Unsafe.As<uint, TBackingType>(ref numericValue) : null,
TypeCode.Int64 => long.TryParse(value, out var numericValue) ? Unsafe.As<long, TBackingType>(ref numericValue) : null,
TypeCode.UInt64 => ulong.TryParse(value, out var numericValue) ? Unsafe.As<ulong, TBackingType>(ref numericValue) : null,
_ => throw new ArgumentOutOfRangeException(nameof(BackingTypeTypeCode), BackingTypeTypeCode, $"Unexpected TypeCode {BackingTypeTypeCode}")
};
public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
{
if (SerializationStrategy is EnumSerializationStrategy.BackingType)
{
WriteAsBackingType(writer, value, options);
}
else if (SerializationStrategy is EnumSerializationStrategy.FirstEnumName)
{
WriteAsFirstEnumName(writer, value, options);
}
else
{
throw new ArgumentOutOfRangeException(nameof(SerializationStrategy), SerializationStrategy, "Unknown serialization strategy");
}
}
public override void WriteAsPropertyName(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
{
if (SerializationStrategy is EnumSerializationStrategy.BackingType)
{
WriteAsPropertyNameAsBackingType(writer, value, options);
}
else if (SerializationStrategy is EnumSerializationStrategy.FirstEnumName)
{
WriteAsPropertyNameAsFirstEnumName(writer, value, options);
}
else
{
throw new ArgumentOutOfRangeException(nameof(SerializationStrategy), SerializationStrategy, "Unknown serialization strategy");
}
}
private void WriteAsBackingType(
Utf8JsonWriter writer,
T value,
[SuppressMessage("ReSharper", "UnusedParameter.Local")]
JsonSerializerOptions options
)
{
var numericValue = ToBackingType(value);
switch (BackingTypeTypeCode)
{
case TypeCode.SByte:
writer.WriteNumberValue(Unsafe.As<TBackingType, sbyte>(ref numericValue));
break;
case TypeCode.Byte:
writer.WriteNumberValue(Unsafe.As<TBackingType, byte>(ref numericValue));
break;
case TypeCode.Int16:
writer.WriteNumberValue(Unsafe.As<TBackingType, short>(ref numericValue));
break;
case TypeCode.UInt16:
writer.WriteNumberValue(Unsafe.As<TBackingType, ushort>(ref numericValue));
break;
case TypeCode.Int32:
writer.WriteNumberValue(Unsafe.As<TBackingType, int>(ref numericValue));
break;
case TypeCode.UInt32:
writer.WriteNumberValue(Unsafe.As<TBackingType, uint>(ref numericValue));
break;
case TypeCode.Int64:
writer.WriteNumberValue(Unsafe.As<TBackingType, long>(ref numericValue));
break;
case TypeCode.UInt64:
writer.WriteNumberValue(Unsafe.As<TBackingType, ulong>(ref numericValue));
break;
default:
throw new ArgumentOutOfRangeException(nameof(BackingTypeTypeCode), BackingTypeTypeCode, $"Unexpected TypeCode {BackingTypeTypeCode}");
}
}
private void WriteAsPropertyNameAsBackingType(
Utf8JsonWriter writer,
T value,
[SuppressMessage("ReSharper", "UnusedParameter.Local")]
JsonSerializerOptions options
)
{
var numericValue = ToBackingType(value);
writer.WritePropertyName($"{numericValue}");
}
private void WriteAsFirstEnumName(
Utf8JsonWriter writer,
T value,
[SuppressMessage("ReSharper", "UnusedParameter.Local")]
JsonSerializerOptions options
)
{
var enumValue = ToFirstEnumName(value);
writer.WriteStringValue(enumValue);
}
private void WriteAsPropertyNameAsFirstEnumName(
Utf8JsonWriter writer,
T value,
[SuppressMessage("ReSharper", "UnusedParameter.Local")]
JsonSerializerOptions options
)
{
var enumValue = ToFirstEnumName(value);
writer.WritePropertyName(enumValue);
}
}
// ReSharper disable once RedundantNullableDirective
#nullable enable
using Aviationexam.GeneratedJsonConverters.Attributes;
namespace Aviationexam.GeneratedJsonConverters;
[DisableEnumJsonConverter]
internal enum EnumSerializationStrategy : byte
{
ProjectDefault,
BackingType,
FirstEnumName,
}
// ReSharper disable once RedundantNullableDirective
#nullable enable
namespace Aviationexam.GeneratedJsonConverters;
internal readonly struct DiscriminatorStruct<T> : IDiscriminatorStruct
{
public T Value { get; init; }
public DiscriminatorStruct(T value)
{
Value = value;
}
}
// ReSharper disable once RedundantNullableDirective
#nullable enable
namespace Aviationexam.GeneratedJsonConverters;
internal interface IDiscriminatorStruct
{
}
#nullable enable
namespace Aviationexam.GeneratedJsonConverters.Attributes;
/// <summary>
/// This is a copy of System.Text.Json.Serialization.JsonDerivedTypeAttribute.
/// It's purpose is to replace this attribute to silence System.Text.Json.Serialization.Metadata.PolymorphicTypeResolver{ThrowHelper.ThrowNotSupportedException_BaseConverterDoesNotSupportMetadata}
///
/// When placed on a type declaration, indicates that the specified subtype should be opted into polymorphic serialization.
/// </summary>
[System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Interface, AllowMultiple = true, Inherited = false)]
internal class JsonDerivedTypeAttribute : System.Text.Json.Serialization.JsonAttribute
{
/// <summary>
/// Initializes a new attribute with specified parameters.
/// </summary>
/// <param name="derivedType">A derived type that should be supported in polymorphic serialization of the declared based type.</param>
public JsonDerivedTypeAttribute(System.Type derivedType)
{
DerivedType = derivedType;
}
/// <summary>
/// Initializes a new attribute with specified parameters.
/// </summary>
/// <param name="derivedType">A derived type that should be supported in polymorphic serialization of the declared base type.</param>
/// <param name="typeDiscriminator">The type discriminator identifier to be used for the serialization of the subtype.</param>
public JsonDerivedTypeAttribute(System.Type derivedType, string typeDiscriminator)
{
DerivedType = derivedType;
TypeDiscriminator = typeDiscriminator;
}
/// <summary>
/// Initializes a new attribute with specified parameters.
/// </summary>
/// <param name="derivedType">A derived type that should be supported in polymorphic serialization of the declared base type.</param>
/// <param name="typeDiscriminator">The type discriminator identifier to be used for the serialization of the subtype.</param>
public JsonDerivedTypeAttribute(System.Type derivedType, int typeDiscriminator)
{
DerivedType = derivedType;
TypeDiscriminator = typeDiscriminator;
}
/// <summary>
/// A derived type that should be supported in polymorphic serialization of the declared base type.
/// </summary>
public System.Type DerivedType { get; }
/// <summary>
/// The type discriminator identifier to be used for the serialization of the subtype.
/// </summary>
public object? TypeDiscriminator { get; }
}
[System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Interface, AllowMultiple = true, Inherited = false)]
internal class JsonDerivedTypeAttribute<TDerivedType> : JsonDerivedTypeAttribute
{
/// <summary>
/// Initializes a new attribute with specified parameters.
/// </summary>
public JsonDerivedTypeAttribute() : base(typeof(TDerivedType))
{
}
/// <summary>
/// Initializes a new attribute with specified parameters.
/// </summary>
/// <param name="typeDiscriminator">The type discriminator identifier to be used for the serialization of the subtype.</param>
public JsonDerivedTypeAttribute(string typeDiscriminator) : base(typeof(TDerivedType), typeDiscriminator)
{
}
/// <summary>
/// Initializes a new attribute with specified parameters.
/// </summary>
/// <param name="typeDiscriminator">The type discriminator identifier to be used for the serialization of the subtype.</param>
public JsonDerivedTypeAttribute(int typeDiscriminator) : base(typeof(TDerivedType), typeDiscriminator)
{
}
}
#nullable enable
namespace Aviationexam.GeneratedJsonConverters.Attributes;
/// <summary>
/// This is a copy of System.Text.Json.Serialization.JsonPolymorphicAttribute.
/// It's purpose is to replace this attribute to silence System.Text.Json.Serialization.Metadata.PolymorphicTypeResolver{ThrowHelper.ThrowNotSupportedException_BaseConverterDoesNotSupportMetadata}
///
/// When placed on a type, indicates that the type should be serialized polymorphically.
/// </summary>
[System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Interface, AllowMultiple = false, Inherited = false)]
internal sealed class JsonPolymorphicAttribute : System.Text.Json.Serialization.JsonAttribute
{
/// <summary>
/// Gets or sets a custom type discriminator property name for the polymorhic type.
/// Uses the default '$type' property name if left unset.
/// </summary>
public string? TypeDiscriminatorPropertyName { get; set; }
/// <summary>
/// Gets or sets the behavior when serializing an undeclared derived runtime type.
/// </summary>
public System.Text.Json.Serialization.JsonUnknownDerivedTypeHandling UnknownDerivedTypeHandling { get; set; }
/// <summary>
/// When set to <see langword="true"/>, instructs the deserializer to ignore any
/// unrecognized type discriminator id's and reverts to the contract of the base type.
/// Otherwise, it will fail the deserialization.
/// </summary>
public bool IgnoreUnrecognizedTypeDiscriminators { get; set; }
}
#nullable enable
namespace PolymorphicGlobalNamespace;
internal class PersonJsonPolymorphicConverter : Aviationexam.GeneratedJsonConverters.PolymorphicJsonConvertor<global::JsonPolymorphicGeneratorDemo.Person>
{
protected override System.ReadOnlySpan<byte> GetDiscriminatorPropertyName() => "$type"u8;
protected override System.Type GetTypeForDiscriminator(
Aviationexam.GeneratedJsonConverters.IDiscriminatorStruct discriminator
) => discriminator switch
{
Aviationexam.GeneratedJsonConverters.DiscriminatorStruct<string> { Value: "Student" } => typeof(JsonPolymorphicGeneratorDemo.Student),
Aviationexam.GeneratedJsonConverters.DiscriminatorStruct<string> { Value: "Teacher" } => typeof(JsonPolymorphicGeneratorDemo.Teacher),
_ => throw new System.ArgumentOutOfRangeException(nameof(discriminator), discriminator, null),
};
protected override Aviationexam.GeneratedJsonConverters.IDiscriminatorStruct GetDiscriminatorForType(
System.Type type
)
{
if (type == typeof(JsonPolymorphicGeneratorDemo.Student))
{
return new Aviationexam.GeneratedJsonConverters.DiscriminatorStruct<string>("Student");
}
if (type == typeof(JsonPolymorphicGeneratorDemo.Teacher))
{
return new Aviationexam.GeneratedJsonConverters.DiscriminatorStruct<string>("Teacher");
}
throw new System.ArgumentOutOfRangeException(nameof(type), type, null);
}
}
// ReSharper disable once RedundantNullableDirective
#nullable enable
using System;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Aviationexam.GeneratedJsonConverters;
internal abstract class PolymorphicJsonConvertor<T> : JsonConverter<T> where T : class
{
private readonly Type _polymorphicType = typeof(T);
protected abstract ReadOnlySpan<byte> GetDiscriminatorPropertyName();
protected abstract Type GetTypeForDiscriminator(IDiscriminatorStruct discriminator);
protected abstract IDiscriminatorStruct GetDiscriminatorForType(Type type);
public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
using var jsonDocument = JsonDocument.ParseValue(ref reader);
var discriminatorPropertyName = GetDiscriminatorPropertyName();
var discriminatorProperty = jsonDocument.RootElement
.GetProperty(discriminatorPropertyName);
IDiscriminatorStruct? typeDiscriminator = null;
if (discriminatorProperty.ValueKind is JsonValueKind.String)
{
typeDiscriminator = new DiscriminatorStruct<string>(discriminatorProperty.GetString()!);
}
else if (discriminatorProperty.ValueKind is JsonValueKind.Number)
{
typeDiscriminator = new DiscriminatorStruct<int>(discriminatorProperty.GetInt32());
}
if (typeDiscriminator is null)
{
var discriminatorPropertyNameString = Encoding.UTF8.GetString(discriminatorPropertyName.ToArray());
throw new JsonException($"Not found discriminator property '{discriminatorPropertyNameString}' for type {_polymorphicType}");
}
var type = GetTypeForDiscriminator(typeDiscriminator);
return (T?) jsonDocument.Deserialize(type, options);
}
public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
{
var instanceType = value.GetType();
writer.WriteStartObject();
var discriminatorPropertyName = GetDiscriminatorPropertyName();
var discriminatorValue = GetDiscriminatorForType(instanceType);
if (discriminatorValue is DiscriminatorStruct<string> discriminatorString)
{
writer.WriteString(discriminatorPropertyName, discriminatorString.Value);
}
else if (discriminatorValue is DiscriminatorStruct<int> discriminatorInt)
{
writer.WriteNumber(discriminatorPropertyName, discriminatorInt.Value);
}
var typeInfo = options.GetTypeInfo(instanceType);
foreach (var p in typeInfo.Properties)
{
if (p.Get is null)
{
continue;
}
writer.WritePropertyName(p.Name);
JsonSerializer.Serialize(writer, p.Get(value), p.PropertyType, options);
}
writer.WriteEndObject();
}
}
#nullable enable
public partial class ProjectJsonSerializerContext
{
public static System.Collections.Generic.IReadOnlyCollection<System.Text.Json.Serialization.JsonConverter> GetPolymorphicConverters() => new System.Text.Json.Serialization.JsonConverter[]
{
new PolymorphicGlobalNamespace.PersonJsonPolymorphicConverter(),
};
public static void UsePolymorphicConverters(
System.Collections.Generic.ICollection<System.Text.Json.Serialization.JsonConverter> optionsConverters
)
{
foreach (var converter in GetPolymorphicConverters())
{
optionsConverters.Add(converter);
}
}
}
// <auto-generated/>
#nullable enable annotations
#nullable disable warnings
// Suppress warnings about [Obsolete] member usage in generated code.
#pragma warning disable CS0618
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Text.Json.SourceGeneration", "7.0.10.6629")]
public partial class ProjectJsonSerializerContext
{
private static global::System.Text.Json.JsonSerializerOptions s_defaultOptions { get; } = new global::System.Text.Json.JsonSerializerOptions()
{
DefaultIgnoreCondition = global::System.Text.Json.Serialization.JsonIgnoreCondition.Never,
IgnoreReadOnlyFields = false,
IgnoreReadOnlyProperties = false,
IncludeFields = false,
WriteIndented = true,
PropertyNamingPolicy = global::System.Text.Json.JsonNamingPolicy.CamelCase
};
private static global::ProjectJsonSerializerContext? s_defaultContext;
/// <summary>
/// The default <see cref="global::System.Text.Json.Serialization.JsonSerializerContext"/> associated with a default <see cref="global::System.Text.Json.JsonSerializerOptions"/> instance.
/// </summary>
public static global::ProjectJsonSerializerContext Default => s_defaultContext ??= new global::ProjectJsonSerializerContext(new global::System.Text.Json.JsonSerializerOptions(s_defaultOptions));
/// <summary>
/// The source-generated options associated with this context.
/// </summary>
protected override global::System.Text.Json.JsonSerializerOptions? GeneratedSerializerOptions { get; } = s_defaultOptions;
/// <inheritdoc/>
public ProjectJsonSerializerContext() : base(null)
{
}
/// <inheritdoc/>
public ProjectJsonSerializerContext(global::System.Text.Json.JsonSerializerOptions options) : base(options)
{
}
private static global::System.Text.Json.Serialization.JsonConverter? GetRuntimeProvidedCustomConverter(global::System.Text.Json.JsonSerializerOptions options, global::System.Type type)
{
global::System.Collections.Generic.IList<global::System.Text.Json.Serialization.JsonConverter> converters = options.Converters;
for (int i = 0; i < converters.Count; i++)
{
global::System.Text.Json.Serialization.JsonConverter? converter = converters[i];
if (converter.CanConvert(type))
{
if (converter is global::System.Text.Json.Serialization.JsonConverterFactory factory)
{
converter = factory.CreateConverter(type, options);
if (converter == null || converter is global::System.Text.Json.Serialization.JsonConverterFactory)
{
throw new global::System.InvalidOperationException(string.Format("The converter '{0}' cannot return null or a JsonConverterFactory instance.", factory.GetType()));
}
}
return converter;
}
}
return null;
}
}
// <auto-generated/>
#nullable enable annotations
#nullable disable warnings
// Suppress warnings about [Obsolete] member usage in generated code.
#pragma warning disable CS0618
public partial class ProjectJsonSerializerContext: global::System.Text.Json.Serialization.Metadata.IJsonTypeInfoResolver
{
/// <inheritdoc/>
public override global::System.Text.Json.Serialization.Metadata.JsonTypeInfo GetTypeInfo(global::System.Type type)
{
if (type == typeof(global::JsonPolymorphicGeneratorDemo.Person[]))
{
return this.PersonArray;
}
if (type == typeof(global::JsonPolymorphicGeneratorDemo.Person))
{
return this.Person;
}
if (type == typeof(global::System.String))
{
return this.String;
}
if (type == typeof(global::JsonPolymorphicGeneratorDemo.Student))
{
return this.Student;
}
if (type == typeof(global::JsonPolymorphicGeneratorDemo.Teacher))
{
return this.Teacher;
}
return null!;
}
global::System.Text.Json.Serialization.Metadata.JsonTypeInfo? global::System.Text.Json.Serialization.Metadata.IJsonTypeInfoResolver.GetTypeInfo(global::System.Type type, global::System.Text.Json.JsonSerializerOptions options)
{
if (type == typeof(global::JsonPolymorphicGeneratorDemo.Person[]))
{
return Create_PersonArray(options, makeReadOnly: false);
}
if (type == typeof(global::JsonPolymorphicGeneratorDemo.Person))
{
return Create_Person(options, makeReadOnly: false);
}
if (type == typeof(global::System.String))
{
return Create_String(options, makeReadOnly: false);
}
if (type == typeof(global::JsonPolymorphicGeneratorDemo.Student))
{
return Create_Student(options, makeReadOnly: false);
}
if (type == typeof(global::JsonPolymorphicGeneratorDemo.Teacher))
{
return Create_Teacher(options, makeReadOnly: false);
}
return null;
}
}
// <auto-generated/>
#nullable enable annotations
#nullable disable warnings
// Suppress warnings about [Obsolete] member usage in generated code.
#pragma warning disable CS0618
public partial class ProjectJsonSerializerContext
{
private global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::JsonPolymorphicGeneratorDemo.Person>? _Person;
/// <summary>
/// Defines the source generated JSON serialization contract metadata for a given type.
/// </summary>
public global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::JsonPolymorphicGeneratorDemo.Person> Person
{
get => _Person ??= Create_Person(Options, makeReadOnly: true);
}
private global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::JsonPolymorphicGeneratorDemo.Person> Create_Person(global::System.Text.Json.JsonSerializerOptions options, bool makeReadOnly)
{
global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::JsonPolymorphicGeneratorDemo.Person>? jsonTypeInfo = null;
global::System.Text.Json.Serialization.JsonConverter? customConverter;
if (options.Converters.Count > 0 && (customConverter = GetRuntimeProvidedCustomConverter(options, typeof(global::JsonPolymorphicGeneratorDemo.Person))) != null)
{
jsonTypeInfo = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreateValueInfo<global::JsonPolymorphicGeneratorDemo.Person>(options, customConverter);
}
else
{
global::System.Text.Json.Serialization.Metadata.JsonObjectInfoValues<global::JsonPolymorphicGeneratorDemo.Person> objectInfo = new global::System.Text.Json.Serialization.Metadata.JsonObjectInfoValues<global::JsonPolymorphicGeneratorDemo.Person>()
{
ObjectCreator = null,
ObjectWithParameterizedConstructorCreator = null,
PropertyMetadataInitializer = _ => PersonPropInit(options),
ConstructorParameterMetadataInitializer = null,
NumberHandling = default,
SerializeHandler = PersonSerializeHandler
};
jsonTypeInfo = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreateObjectInfo<global::JsonPolymorphicGeneratorDemo.Person>(options, objectInfo);
}
if (makeReadOnly)
{
jsonTypeInfo.MakeReadOnly();
}
return jsonTypeInfo;
}
private static global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo[] PersonPropInit(global::System.Text.Json.JsonSerializerOptions options)
{
global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo[] properties = new global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo[1];
global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<global::System.String> info0 = new global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<global::System.String>()
{
IsProperty = true,
IsPublic = true,
IsVirtual = false,
DeclaringType = typeof(global::JsonPolymorphicGeneratorDemo.Person),
Converter = null,
Getter = static (obj) => ((global::JsonPolymorphicGeneratorDemo.Person)obj).Name!,
Setter = static (obj, value) => ((global::JsonPolymorphicGeneratorDemo.Person)obj).Name = value!,
IgnoreCondition = null,
HasJsonInclude = false,
IsExtensionData = false,
NumberHandling = default,
PropertyName = "Name",
JsonPropertyName = null
};
global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo propertyInfo0 = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreatePropertyInfo<global::System.String>(options, info0);
properties[0] = propertyInfo0;
return properties;
}
// Intentionally not a static method because we create a delegate to it. Invoking delegates to instance
// methods is almost as fast as virtual calls. Static methods need to go through a shuffle thunk.
private void PersonSerializeHandler(global::System.Text.Json.Utf8JsonWriter writer, global::JsonPolymorphicGeneratorDemo.Person? value)
{
if (value == null)
{
writer.WriteNullValue();
return;
}
writer.WriteStartObject();
writer.WriteString(PropName_name, value.Name);
writer.WriteEndObject();
}
}
// <auto-generated/>
#nullable enable annotations
#nullable disable warnings
// Suppress warnings about [Obsolete] member usage in generated code.
#pragma warning disable CS0618
public partial class ProjectJsonSerializerContext
{
private global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::JsonPolymorphicGeneratorDemo.Person[]>? _PersonArray;
/// <summary>
/// Defines the source generated JSON serialization contract metadata for a given type.
/// </summary>
public global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::JsonPolymorphicGeneratorDemo.Person[]> PersonArray
{
get => _PersonArray ??= Create_PersonArray(Options, makeReadOnly: true);
}
private global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::JsonPolymorphicGeneratorDemo.Person[]> Create_PersonArray(global::System.Text.Json.JsonSerializerOptions options, bool makeReadOnly)
{
global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::JsonPolymorphicGeneratorDemo.Person[]>? jsonTypeInfo = null;
global::System.Text.Json.Serialization.JsonConverter? customConverter;
if (options.Converters.Count > 0 && (customConverter = GetRuntimeProvidedCustomConverter(options, typeof(global::JsonPolymorphicGeneratorDemo.Person[]))) != null)
{
jsonTypeInfo = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreateValueInfo<global::JsonPolymorphicGeneratorDemo.Person[]>(options, customConverter);
}
else
{
global::System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues<global::JsonPolymorphicGeneratorDemo.Person[]> info = new global::System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues<global::JsonPolymorphicGeneratorDemo.Person[]>()
{
ObjectCreator = null,
NumberHandling = default,
SerializeHandler = PersonArraySerializeHandler
};
jsonTypeInfo = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreateArrayInfo<global::JsonPolymorphicGeneratorDemo.Person>(options, info);
}
if (makeReadOnly)
{
jsonTypeInfo.MakeReadOnly();
}
return jsonTypeInfo;
}
// Intentionally not a static method because we create a delegate to it. Invoking delegates to instance
// methods is almost as fast as virtual calls. Static methods need to go through a shuffle thunk.
private void PersonArraySerializeHandler(global::System.Text.Json.Utf8JsonWriter writer, global::JsonPolymorphicGeneratorDemo.Person[]? value)
{
if (value == null)
{
writer.WriteNullValue();
return;
}
writer.WriteStartArray();
for (int i = 0; i < value.Length; i++)
{
PersonSerializeHandler(writer, value[i]!);
}
writer.WriteEndArray();
}
}
// <auto-generated/>
#nullable enable annotations
#nullable disable warnings
// Suppress warnings about [Obsolete] member usage in generated code.
#pragma warning disable CS0618
public partial class ProjectJsonSerializerContext
{
private static readonly global::System.Text.Json.JsonEncodedText PropName_name = global::System.Text.Json.JsonEncodedText.Encode("name");
}
// <auto-generated/>
#nullable enable annotations
#nullable disable warnings
// Suppress warnings about [Obsolete] member usage in generated code.
#pragma warning disable CS0618
public partial class ProjectJsonSerializerContext
{
private global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::System.String>? _String;
/// <summary>
/// Defines the source generated JSON serialization contract metadata for a given type.
/// </summary>
public global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::System.String> String
{
get => _String ??= Create_String(Options, makeReadOnly: true);
}
private global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::System.String> Create_String(global::System.Text.Json.JsonSerializerOptions options, bool makeReadOnly)
{
global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::System.String>? jsonTypeInfo = null;
global::System.Text.Json.Serialization.JsonConverter? customConverter;
if (options.Converters.Count > 0 && (customConverter = GetRuntimeProvidedCustomConverter(options, typeof(global::System.String))) != null)
{
jsonTypeInfo = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreateValueInfo<global::System.String>(options, customConverter);
}
else
{
jsonTypeInfo = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreateValueInfo<global::System.String>(options, global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.StringConverter);
}
if (makeReadOnly)
{
jsonTypeInfo.MakeReadOnly();
}
return jsonTypeInfo;
}
}
// <auto-generated/>
#nullable enable annotations
#nullable disable warnings
// Suppress warnings about [Obsolete] member usage in generated code.
#pragma warning disable CS0618
public partial class ProjectJsonSerializerContext
{
private global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::JsonPolymorphicGeneratorDemo.Student>? _Student;
/// <summary>
/// Defines the source generated JSON serialization contract metadata for a given type.
/// </summary>
public global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::JsonPolymorphicGeneratorDemo.Student> Student
{
get => _Student ??= Create_Student(Options, makeReadOnly: true);
}
private global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::JsonPolymorphicGeneratorDemo.Student> Create_Student(global::System.Text.Json.JsonSerializerOptions options, bool makeReadOnly)
{
global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::JsonPolymorphicGeneratorDemo.Student>? jsonTypeInfo = null;
global::System.Text.Json.Serialization.JsonConverter? customConverter;
if (options.Converters.Count > 0 && (customConverter = GetRuntimeProvidedCustomConverter(options, typeof(global::JsonPolymorphicGeneratorDemo.Student))) != null)
{
jsonTypeInfo = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreateValueInfo<global::JsonPolymorphicGeneratorDemo.Student>(options, customConverter);
}
else
{
global::System.Text.Json.Serialization.Metadata.JsonObjectInfoValues<global::JsonPolymorphicGeneratorDemo.Student> objectInfo = new global::System.Text.Json.Serialization.Metadata.JsonObjectInfoValues<global::JsonPolymorphicGeneratorDemo.Student>()
{
ObjectCreator = static () => new global::JsonPolymorphicGeneratorDemo.Student(),
ObjectWithParameterizedConstructorCreator = null,
PropertyMetadataInitializer = _ => StudentPropInit(options),
ConstructorParameterMetadataInitializer = null,
NumberHandling = default,
SerializeHandler = StudentSerializeHandler
};
jsonTypeInfo = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreateObjectInfo<global::JsonPolymorphicGeneratorDemo.Student>(options, objectInfo);
}
if (makeReadOnly)
{
jsonTypeInfo.MakeReadOnly();
}
return jsonTypeInfo;
}
private static global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo[] StudentPropInit(global::System.Text.Json.JsonSerializerOptions options)
{
global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo[] properties = new global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo[1];
global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<global::System.String> info0 = new global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<global::System.String>()
{
IsProperty = true,
IsPublic = true,
IsVirtual = false,
DeclaringType = typeof(global::JsonPolymorphicGeneratorDemo.Person),
Converter = null,
Getter = static (obj) => ((global::JsonPolymorphicGeneratorDemo.Person)obj).Name!,
Setter = static (obj, value) => ((global::JsonPolymorphicGeneratorDemo.Person)obj).Name = value!,
IgnoreCondition = null,
HasJsonInclude = false,
IsExtensionData = false,
NumberHandling = default,
PropertyName = "Name",
JsonPropertyName = null
};
global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo propertyInfo0 = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreatePropertyInfo<global::System.String>(options, info0);
properties[0] = propertyInfo0;
return properties;
}
// Intentionally not a static method because we create a delegate to it. Invoking delegates to instance
// methods is almost as fast as virtual calls. Static methods need to go through a shuffle thunk.
private void StudentSerializeHandler(global::System.Text.Json.Utf8JsonWriter writer, global::JsonPolymorphicGeneratorDemo.Student? value)
{
if (value == null)
{
writer.WriteNullValue();
return;
}
writer.WriteStartObject();
writer.WriteString(PropName_name, value.Name);
writer.WriteEndObject();
}
}
// <auto-generated/>
#nullable enable annotations
#nullable disable warnings
// Suppress warnings about [Obsolete] member usage in generated code.
#pragma warning disable CS0618
public partial class ProjectJsonSerializerContext
{
private global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::JsonPolymorphicGeneratorDemo.Teacher>? _Teacher;
/// <summary>
/// Defines the source generated JSON serialization contract metadata for a given type.
/// </summary>
public global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::JsonPolymorphicGeneratorDemo.Teacher> Teacher
{
get => _Teacher ??= Create_Teacher(Options, makeReadOnly: true);
}
private global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::JsonPolymorphicGeneratorDemo.Teacher> Create_Teacher(global::System.Text.Json.JsonSerializerOptions options, bool makeReadOnly)
{
global::System.Text.Json.Serialization.Metadata.JsonTypeInfo<global::JsonPolymorphicGeneratorDemo.Teacher>? jsonTypeInfo = null;
global::System.Text.Json.Serialization.JsonConverter? customConverter;
if (options.Converters.Count > 0 && (customConverter = GetRuntimeProvidedCustomConverter(options, typeof(global::JsonPolymorphicGeneratorDemo.Teacher))) != null)
{
jsonTypeInfo = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreateValueInfo<global::JsonPolymorphicGeneratorDemo.Teacher>(options, customConverter);
}
else
{
global::System.Text.Json.Serialization.Metadata.JsonObjectInfoValues<global::JsonPolymorphicGeneratorDemo.Teacher> objectInfo = new global::System.Text.Json.Serialization.Metadata.JsonObjectInfoValues<global::JsonPolymorphicGeneratorDemo.Teacher>()
{
ObjectCreator = static () => new global::JsonPolymorphicGeneratorDemo.Teacher(),
ObjectWithParameterizedConstructorCreator = null,
PropertyMetadataInitializer = _ => TeacherPropInit(options),
ConstructorParameterMetadataInitializer = null,
NumberHandling = default,
SerializeHandler = TeacherSerializeHandler
};
jsonTypeInfo = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreateObjectInfo<global::JsonPolymorphicGeneratorDemo.Teacher>(options, objectInfo);
}
if (makeReadOnly)
{
jsonTypeInfo.MakeReadOnly();
}
return jsonTypeInfo;
}
private static global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo[] TeacherPropInit(global::System.Text.Json.JsonSerializerOptions options)
{
global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo[] properties = new global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo[1];
global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<global::System.String> info0 = new global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<global::System.String>()
{
IsProperty = true,
IsPublic = true,
IsVirtual = false,
DeclaringType = typeof(global::JsonPolymorphicGeneratorDemo.Person),
Converter = null,
Getter = static (obj) => ((global::JsonPolymorphicGeneratorDemo.Person)obj).Name!,
Setter = static (obj, value) => ((global::JsonPolymorphicGeneratorDemo.Person)obj).Name = value!,
IgnoreCondition = null,
HasJsonInclude = false,
IsExtensionData = false,
NumberHandling = default,
PropertyName = "Name",
JsonPropertyName = null
};
global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo propertyInfo0 = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreatePropertyInfo<global::System.String>(options, info0);
properties[0] = propertyInfo0;
return properties;
}
// Intentionally not a static method because we create a delegate to it. Invoking delegates to instance
// methods is almost as fast as virtual calls. Static methods need to go through a shuffle thunk.
private void TeacherSerializeHandler(global::System.Text.Json.Utf8JsonWriter writer, global::JsonPolymorphicGeneratorDemo.Teacher? value)
{
if (value == null)
{
writer.WriteNullValue();
return;
}
writer.WriteStartObject();
writer.WriteString(PropName_name, value.Name);
writer.WriteEndObject();
}
}
Usefull
Download Example (.NET C# )
Share jsonConverterSourceGenerator
https://ignatandrei.github.io/RSCG_Examples/v2/docs/jsonConverterSourceGenerator