using System.Collections;
using System.Collections.Generic;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Metadata;
using System.Text.Json.Nodes;
internal class BaseCommand
internal sealed class CreateResourceCommand : BaseCommand
public const string CommandName = "CreateResourceCommand";
internal sealed class CreateResourceWithAttributeCommand : BaseCommand
public const string CommandName = "CreateResourceWithAttributeCommand";
[JsonPropertyName("commandAttribute")]
public const TestEnum Attribute = TestEnum.TestValue;
public static partial class JsonExtensions
public static Action<JsonTypeInfo> AddOptInConstMembers<TOptInAttribute>(Type type) where TOptInAttribute : System.Attribute =>
if (typeInfo.Type == type)
AddOptInConstMembers<TOptInAttribute>(typeInfo);
public static void AddOptInConstMembers<TOptInAttribute>(JsonTypeInfo typeInfo) where TOptInAttribute : System.Attribute
if (typeInfo.Kind != JsonTypeInfoKind.Object)
foreach (var field in typeInfo.Type.GetConstants().Where(f => Attribute.IsDefined(f, typeof(TOptInAttribute))))
var name = field.GetCustomAttribute<JsonPropertyNameAttribute>()?.Name ?? typeInfo.Options.PropertyNamingPolicy?.ConvertName(field.Name) ?? field.Name;
var value = field.GetValue(null);
var propertyInfo = typeInfo.CreateJsonPropertyInfo(value?.GetType() ?? field.FieldType, name);
propertyInfo.Get = (o) => value;
propertyInfo.CustomConverter = field.GetCustomAttribute<JsonConverterAttribute>()?.ConverterType is {} converterType
? (JsonConverter?)Activator.CreateInstance(converterType)
typeInfo.Properties.Add(propertyInfo);
static IEnumerable<FieldInfo> GetConstants(this Type type) =>
type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.FlattenHierarchy)
.Where(fi => fi.IsLiteral && !fi.IsInitOnly);
public static void Test()
var command = new CreateResourceCommand();
var options = new JsonSerializerOptions
TypeInfoResolver = new DefaultJsonTypeInfoResolver
Modifiers = { JsonExtensions.AddOptInConstMembers<JsonIncludeAttribute> },
var json = JsonSerializer.Serialize(command, options);
Assert.AreEqual("""{"CommandName":"CreateResourceCommand"}""", json);
var command = new CreateResourceWithAttributeCommand();
var options = new JsonSerializerOptions
TypeInfoResolver = new DefaultJsonTypeInfoResolver
Modifiers = { JsonExtensions.AddOptInConstMembers<JsonIncludeAttribute> },
Converters = { new JsonStringEnumConverter() },
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
var json = JsonSerializer.Serialize(command, options);
Assert.AreEqual("""{"commandName":"CreateResourceWithAttributeCommand","commandAttribute":"TestValue"}""", json);
public static void Main()
Console.WriteLine("Environment version: {0} ({1}), {2}", System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription , Environment.Version, Environment.OSVersion);
Console.WriteLine("System.Text.Json version: " + typeof(JsonSerializer).Assembly.FullName);
Console.WriteLine("Failed with unhandled exception: ");