Skip to content

[Bug]: Example Null-Handling Seems Inverted #3801

@pinkfloydx33

Description

@pinkfloydx33

Describe the bug

I was actually happy to see #3793 as this was a minor gap for us in the .NET 10 upgrade where we had some examples that were explicitly/intentionally written to the API Spec as null.

However moving to the new package 10.1.4 seems to exhibit strange behavior. I am only allowed to write a null example to the document if the data type is JsonSchemaType.String but not JsonSchemaTypeString | JsonSchemaType.Null.

var isStringType = type is { } value &&
value.HasFlag(JsonSchemaType.String) &&
!value.HasFlag(JsonSchemaType.Null);
if (isStringType)
{
return string.Equals(exampleString, "null") ? JsonNullSentinel.JsonNull : JsonValue.Create(exampleString);
}

This seems inverted! I can set example=null on a non-nullable string, but not on a nullable string?
It also seems a bit funny that it's limited to strings and not any nullable type

Expected behavior

At the very least I would expect to be able to set the example value to null if the property itself supports being null i.e. with JsonSchemaType.Null | JsonSchemaType.String

Though I probably would not limit this to just strings at all! Perhaps something like this could suffice for any type of property:

var type = schema?.ResolveType(schemaRepository);
if (type is { } value && value.HasFlag(JsonSchemaType.Null) && string.Equals(exampleString, "null"))
{
    return JsonNullSentinel.JsonNull;
}

// rest of method

Actual behavior

Cannot write "example": null to document if schema resolves to JsonSchemaTypeString | JsonSchemaType.Null
Cannot write "example": null for numeric or other properties that have the JsonSchemaType.Null flag

Steps to reproduce

Consider this data type:

public sealed class MyType
{
    /// <example>null</example>
    [Required]
    public string Ex0 { get; set; } = null!;  
    /// <example>null</example>
    public string? Ex1 { get; set; }
    /// <example>null</example>
    public Guid Ex2 { get; set; }
    /// <example>null</example>
    public Guid? Ex3 { get; set; }
    /// <example>null</example>
    public int Ex4 { get; set; }
    /// <example>null</example>
    public int? Ex5 { get; set; }
    /// <example>3</example>
    public int? Ex6 { get; set; }
}

The API Specification generated will produce

Field Expected Example Actual Example Correct
Ex0 omitted "example": null
Ex1 "example": null omitted
Ex2 omitted "example": null
Ex3 "example": null omitted
Ex4 omitted omitted
Ex5 "example": null omitted
Ex6 "example": 3 "example": 3

Exception(s) (if any)

No response

Swashbuckle.AspNetCore version

10.1.4

.NET Version

10

Anything else?

As a work-around, you can write the literal value of JsonNullSentinel.NullValue as your example and it will get converted just fine:

public sealed class MyType
{
    /// <example>openapi-json-null-sentinel-value-2BF93600-0FE4-4250-987A-E5DDB203E464</example>  
    public string? Ex1 { get; set; }
}

However that is a bit heavy handed and likely an implementation detail!

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions