RSCG – jsonConverterSourceGenerator
RSCG – jsonConverterSourceGenerator
name | jsonConverterSourceGenerator |
nuget | https://www.nuget.org/packages/Aviationexam.GeneratedJsonConverters.SourceGenerator/ |
link | https://github.com/aviationexam/json-converter-source-generator |
author | Aviationexam |
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
Leave a Reply