Skip to content

v3.0.3 renders defaultValue: "" although @Schema does not mention it #3285

@sebsprenger

Description

@sebsprenger

Describe the bug

We updated from "org.springdoc:springdoc-openapi-starter-webmvc-ui:3.0.2" to "org.springdoc:springdoc-openapi-starter-webmvc-ui:3.0.3" and since then noticed, that code like this

    @Getter
    @Accessors(fluent = true)
    @AllArgsConstructor
    public static class Amount {
        @Schema(description = "amount in smallest unit of its currency, e.g. cent", requiredMode = REQUIRED)
        @JsonProperty("value")
        private Integer value;

        @Schema(description = "ISO Standard, e.g. 'EUR'", requiredMode = REQUIRED)
        @JsonProperty("currency")
        private String currency;
    }

is being rendered to

components:
  schemas:
    Amount:
      type: object
      properties:
        currency:
          type: string
          default: ""
          description: "ISO Standard, e.g. 'EUR'"
        value:
          type: integer
          format: int32
          default: ""
          description: "amount in smallest unit of its currency, e.g. cent"

The default: "" is new. It does not make any sense for an integer to have a default value of empty string. In other cases we added validation annotation like @NotBlank which effectively adds an minLength: 1 to the OpenAPI spec - there a default: "" is also not valid.

To Reproduce
Steps to reproduce the behavior:

  • Using "org.springframework.boot:spring-boot-starter-webmvc:4.0.6"
  • Using "org.springdoc:springdoc-openapi-starter-webmvc-ui:3.0.3"
  • Using "io.swagger.core.v3:swagger-annotations:2.2.49"
  • Working with yaml

Code example:

package com.example;

import io.swagger.v3.oas.annotations.media.Schema;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class SpringDocDefaultValueController {

    @GetMapping("/defaultValueDemo")
    ResponseEntity<TestResponse> endpoint() {
        var response = new TestResponse(true, 42, Currency.EUR, "hello world");
        return ResponseEntity.ok(response);
    }

    private record TestResponse(
            @Schema(description = "a bool")
            boolean myBool,
            @Schema(description = "an int")
            int myInt,
            @Schema(description = "an enum")
            Currency myEnum,
            @Schema(description = "a string")
            String myString) {}

    private enum Currency {EUR, USD}
}

v3.0.3 renders into

openapi: 3.1.0
info:
  description: test
  title: test
  version: 1.0.0
servers:
- description: test
  url: https://example.com
paths:
  /defaultValueDemo:
    get:
      operationId: endpoint
      responses:
        "200":
          content:
            '*/*':
              schema:
                $ref: "#/components/schemas/TestResponse"
          description: OK
      tags:
      - spring-doc-default-value-controller
components:
  schemas:
    TestResponse:
      type: object
      properties:
        myBool:
          type: boolean
          default: false
          description: a bool
        myEnum:
          type: string
          default: ""
          description: an enum
          enum:
          - EUR
          - USD
        myInt:
          type: integer
          format: int32
          default: ""
          description: an int
        myString:
          type: string
          default: ""
          description: a string

Expected behavior

We expect the default values not to be there at all, since we did not specify them in the @Schema annotation. Furthermore, we expect default values to at least have the correct type. Empty string is not a valid fit for an integer.
v3.0.2 renders into the following yaml, which we consider "more correct".

openapi: 3.1.0
info:
  description: test
  title: test
  version: 1.0.0
servers:
- description: test
  url: https://example.com
paths:
  /defaultValueDemo:
    get:
      operationId: endpoint
      responses:
        "200":
          content:
            '*/*':
              schema:
                $ref: "#/components/schemas/TestResponse"
          description: OK
      tags:
      - spring-doc-default-value-controller
components:
  schemas:
    TestResponse:
      type: object
      properties:
        myBool:
          type: boolean
          description: a bool
        myEnum:
          type: string
          description: an enum
          enum:
          - EUR
          - USD
        myInt:
          type: integer
          format: int32
          description: an int
        myString:
          type: string
          description: a string

Additional context
Problems were initially exposed by https://hub.docker.com/r/p1c2u/openapi-spec-validator in our pipeline.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions