RicoSuter / NJsonSchema

JSON Schema reader, generator and validator for .NET
http://NJsonSchema.org
MIT License
1.37k stars 529 forks source link

C#11 required member support when generating a schema from a type #1672

Open wuzzeb opened 7 months ago

wuzzeb commented 7 months ago

C# 11 added a required member and starting in .NET8, System.Text.Json now has full support for deserializing required members, giving an error if the member is missing. The compiler creates a System.Runtime.CompilerServices.RequiredMemberAttribute so JsonSchemaGenerator should check for this attribute in addition to the other required attributes.

I was able to temporarily support this by the following custom schema processor, but it is slightly hacky. I couldn't find a way of determining the final json property name from the Namotion ContextualPropertyInfo, is there one? I instead just re-looked up the JsonName attribute (only a few properties in our codebase have that name attribute, most are just named directly). Also, I had another hack to determine if it was a derived type by looking at AllOf... but it works for our schema.

    public class RequiredModifierSchemaProcessor : ISchemaProcessor
    {
      public void Process(SchemaProcessorContext ctx)
      {
        foreach (var prop in ctx.ContextualType.Properties)
        {
          if (prop.PropertyInfo.DeclaringType != ctx.ContextualType.Type)
          {
            continue;
          }
          if (prop.GetAttribute<System.Runtime.CompilerServices.RequiredMemberAttribute>(false) != null)
          {
            string name = prop.Name;
            var jsonNameAttr = prop.GetAttribute<System.Text.Json.Serialization.JsonPropertyNameAttribute>(
              false
            );
            if (jsonNameAttr != null)
            {
              name = jsonNameAttr.Name;
            }
            if (ctx.Schema.AllOf.Count > 1)
            {
              ctx.Schema.AllOf.ElementAt(1).RequiredProperties.Add(name);
            }
            else
            {
              ctx.Schema.RequiredProperties.Add(name);
            }
          }
        }
      }
    }