RSCG – jsonConverterSourceGenerator
Json Polymorphic generator
This is how you can use jsonConverterSourceGenerator .
The code that you start with is
<project sdk="Microsoft.NET.Sdk">
<propertygroup>
<outputtype>Exe</outputtype>
<targetframework>net7.0</targetframework>
<implicitusings>enable</implicitusings>
<nullable>enable</nullable>
</propertygroup>
<itemgroup>
</itemgroup>
<itemgroup>
<packagereference privateassets="all" version="0.1.11" include="Aviationexam.GeneratedJsonConverters.SourceGenerator">
</packagereference>
<propertygroup>
<emitcompilergeneratedfiles>true</emitcompilergeneratedfiles>
<compilergeneratedfilesoutputpath>$(BaseIntermediateOutputPath)\GX</compilergeneratedfilesoutputpath>
</propertygroup>
</itemgroup>
The code that you will use is
//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());
}
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;
}
}
//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);
}
}
}
The code that is generated is
// ReSharper disable once CheckNamespace
namespace Aviationexam.GeneratedJsonConverters.Attributes;
/// <summary>
/// When placed on an enum, indicates that generator should not report missing <see cref="EnumJsonConverterAttribute">
/// </see></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.
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 name="typeDiscriminator">The type discriminator identifier to be used for the serialization of the subtype.
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 name="typeDiscriminator">The type discriminator identifier to be used for the serialization of the subtype.
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.
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.
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.
/// </see></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.9.1816")]
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.
/// </see></see></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();
}
}
Code and pdf at
https://ignatandrei.github.io/RSCG_Examples/v2/docs/jsonConverterSourceGenerator