NJsonSchema icon indicating copy to clipboard operation
NJsonSchema copied to clipboard

Make TypeResolverBase.RemoveNullability virtual for extendability

Open SamuelBerger opened this issue 2 years ago • 0 comments

We use JsonSchema.OneOf with multiple JsonSchemas and generate TypeScript union types out of it.

The current implementation of TypeResolverBase.RemoveNullability "destroys" the JsonSchema.OneOf collection to the first non nullable item:

        /// <summary>Removes a nullable oneOf reference if available.</summary>
        /// <param name="schema">The schema.</param>
        /// <returns>The actually resolvable schema</returns>
        public JsonSchema RemoveNullability(JsonSchema schema)
        {
            // TODO: Method on JsonSchema4?
            return schema.OneOf.FirstOrDefault(o => !o.IsNullable(SchemaType.JsonSchema)) ?? schema;
        }

So we end up with the first non nullable item instead of the whole OneOf collection with multiple non nullable items.

Currently we use an ugly hack in GetOrGenerateTypeName to circumvent the problem:

  • setting all items to IsNullableRaw = true (so RemoveNullability does not replace our OneOf schema with the first item)
  • call the real GetOrGenerateTypeName
  • setting all items back to IsNullableRaw = null
    public class MyTypeScriptTypeResolver : TypeScriptTypeResolver
    {
        public MyTypeScriptTypeResolver(TypeScriptGeneratorSettings settings) : base(settings) { }

        public override string GetOrGenerateTypeName(JsonSchema schema, string typeNameHint) {
            if (schema.OneOf.Count > 1) {
                // hack to escape the RemoveNullability destroying our discriminated union
                foreach (var item in schema.OneOf) {
                    item.IsNullableRaw = true;
                }

                var name = base.GetOrGenerateTypeName(schema, typeNameHint);

                foreach (var item in schema.OneOf) {
                    item.IsNullableRaw = null;
                }

                return name;
            }

            return base.GetOrGenerateTypeName(schema, typeNameHint);
        }
    }  

Making TypeResolverBase.RemoveNullability virtual gives the possibility to override the current behaviour.

SamuelBerger avatar Aug 07 '22 16:08 SamuelBerger