Make Swashbuckle describe a reference type property as nullable, or make NSwag decorate the client side as Default rather than DisallowNull

Viewed 784

I've a DTO that looks like this:

public class OrderDto{
  public CustomerDto Customer{get;set;}
  public ProductDto[] Products{get;set;}
}

When Swashbuckle describes it in an OpenAPI 3 spec, neither property appears in the required list, and the Customer property is not marked with any nullable but the Products property is marked as nullable: true.

"OrderDto": {
    "type": "object",
    "properties": {
      "customer": {
        "$ref": "#/components/schemas/CustomerDto"
      },
      "products": {
        "type": "array",
        "items": {
          "$ref": "#/components/schemas/ProductDto"
        },
        "nullable": true
      }
    },
    "additionalProperties": false
  },

On the client side I'm getting deser errors if I don't set the Customer to something on the server side:

Newtonsoft.Json.JsonSerializationException: 'Required property 'customer' expects a non-null value

The JSON from the server (ser'd by System.Text.Json by the way, not Newtonsoft) looks like:

{"customer":null,"products":[]}

NSwag has decorated the client side class with [Newtonsoft.Json.JsonProperty("customer", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] with the full stub class looking like this:

[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.5.2.0 (Newtonsoft.Json v11.0.0.0)")]
public partial class OrderDto
{    
    [Newtonsoft.Json.JsonProperty("customer", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
    public CustomerDto Customer { get; set; }

    [Newtonsoft.Json.JsonProperty("products", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
    public System.Collections.Generic.ICollection<ProductDto> Products { get; set; }
}

and I'm now trying to find out what I need to change and where to get a more permissive behavior:

Ultimately I'd like to be able to not set Customer to anything on the server side, send it to the client and regardless of whether it ser's as null or is missing from the JSON entirely:

{
  customer: null,
  products: [ ... ]
}

{
  products: [ ... ]
}

and I'd like the client side (also a C# app) to deser this and give me an object where the Customer property is null (default)

Which tool is behaving correctly per the desired behavior?

Should I be changing how Swashbuckle generates the OA3 spec (and how is it done?), or should I be changing how NSwag interprets the generated spec?

1 Answers

I applied this in the startup config:

services.AddSwaggerGen(c =>
{
    ...
    c.UseAllOfToExtendReferenceSchemas();

it seems a bit of a blunt instrument, but it makes everything nullable, which changes NSwag's Required generation from to DisallowNull to Default for reference types

Related