swagger-core icon indicating copy to clipboard operation
swagger-core copied to clipboard

ArraySchema with anyOf is setting type of the items to "string"

Open NiFNi opened this issue 11 months ago • 0 comments

Hi!

I am using Spring Boot (3.2.3) with springdoc-openapi-starter-webmvc-ui (2.2.20). I have a controller annotated like this:

    @ApiResponse(responseCode = "200",
            content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
                    array = @ArraySchema(schema = @Schema(anyOf = {
                            Dto1.class,
                            Dto2.class
                    }))))
    @GetMapping
    public List<? extends AbstractDto> get() {
        return List.of();
    }

This results in an API specification looking like this:

{
   "openapi": "3.0.1",
   "info": {
       "title": "OpenAPI definition",
       "version": "v0"
   },
   "servers": [
       {
           "url": "http://localhost:8080",
           "description": "Generated server url"
       }
   ],
   "paths": {
       "/": {
           "get": {
               "tags": [
                   "controller"
               ],
               "operationId": "get_1",
               "responses": {
                   "200": {
                       "description": "OK",
                       "content": {
                           "application/json": {
                               "schema": {
                                   "type": "array",
                                   "items": {
                                       "type": "string",
                                       "anyOf": [
                                           {
                                               "$ref": "#/components/schemas/Dto1"
                                           },
                                           {
                                               "$ref": "#/components/schemas/Dto2"
                                           }
                                       ]
                                   }
                               }
                           }
                       }
                   }
               }
           }
       }
   },
   "components": {
       "schemas": {
           "Dto1": {
               "type": "object"
           },
           "Dto2": {
               "type": "object"
           }
       }
   }
}

As you can see the type of the items in the array is set to string which looks wrong and also results in swagger-ui rendering the API wrong. Tracking the code led me to this line which sets the type to "string": https://github.com/swagger-api/swagger-core/blob/3fcc473c33c56f306902853a451020926ad691ea/modules/swagger-core/src/main/java/io/swagger/v3/core/util/AnnotationsUtils.java#L1745

I don't really understand why this is done. As a workaround to get it working correctly I added an explicit type to the items like this which atleast makes swagger-ui render the anyOf correctly:

    @ApiResponse(responseCode = "200",
            content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
                    array = @ArraySchema(schema = @Schema(anyOf = {
                            Dto1.class,
                            Dto2.class
                    }, type = "object"))))
    @GetMapping
    public List<? extends AbstractDto> get() {
        return List.of();
    }

What I would have expected in the first place is that the type is not added to the items at all if an anyOf is included.

NiFNi avatar Mar 05 '24 07:03 NiFNi