Нулевой ApiResponse при миграции из springfox в springdoc - PullRequest
3 голосов
/ 30 апреля 2020

Я пытаюсь перейти с springfox-swagger2 (OpenAPI 2) на springdoc-openapi-ui (OpenAPI 3), чтобы сгенерировать документацию.

Вот пример маршрута:

@RequestMapping("/api/object/")
public interface IObjectController {

    @RequestMapping(path = "v1/{param}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    @ResponseStatus(value = HttpStatus.OK)
    ObjectDto getObjectByParamV1(@PathVariable("param") String code);
}

Генерация Swagger отлично работала с springfox-swagger2, однако я получил следующую проблему с springdoc:

Null key for a Map not allowed in JSON (use a converting NullKeySerializer?)
(through reference chain: io.swagger.v3.oas.models.OpenAPI["paths"]->
io.swagger.v3.oas.models.Paths["/api/object/v1/{param}"]->io.swagger.v3.oas.models.PathItem["get"]->
io.swagger.v3.oas.models.Operation["responses"]->io.swagger.v3.oas.models.responses.ApiResponses["null"])

Действительно, OpenAPI пытается сериализовать следующий объект:

responses: class ApiResponses {
            {null=class ApiResponse {
                description: default response
                headers: null
                content: class Content {
                    {*/*=class MediaType {
                        schema: class ComposedSchema {
                            class Schema {
                                type: null
                                format: null
                                $ref: null
                                description: null
                                title: null
                                multipleOf: null
                                maximum: null
                                exclusiveMaximum: null
                                minimum: null
                                exclusiveMinimum: null
                                maxLength: null
                                minLength: null
                                pattern: null
                                maxItems: null
                                minItems: null
                                uniqueItems: null
                                maxProperties: null
                                minProperties: null
                                required: null
                                not: null
                                properties: null
                                additionalProperties: null
                                nullable: null
                                readOnly: null
                                writeOnly: null
                                example: null
                                externalDocs: null
                                deprecated: null
                                discriminator: null
                                xml: null
                            }
                            allOf: null
                            anyOf: null
                            oneOf: [class Schema {
                                type: object
                                format: null
                                $ref: null
                                description: null
                                title: null
                                multipleOf: null
                                maximum: null
                                exclusiveMaximum: null
                                minimum: null
                                exclusiveMinimum: null
                                maxLength: null
                                minLength: null
                                pattern: null
                                maxItems: null
                                minItems: null
                                uniqueItems: null
                                maxProperties: null
                                minProperties: null
                                required: null
                                not: null
                                properties: null
                                additionalProperties: null
                                nullable: null
                                readOnly: null
                                writeOnly: null
                                example: null
                                externalDocs: null
                                deprecated: null
                                discriminator: null
                                xml: null
                            }, class StringSchema {
                                class Schema {
                                    type: string
                                    format: null
                                    $ref: null
                                    description: null
                                    title: null
                                    multipleOf: null
                                    maximum: null
                                    exclusiveMaximum: null
                                    minimum: null
                                    exclusiveMinimum: null
                                    maxLength: null
                                    minLength: null
                                    pattern: null
                                    maxItems: null
                                    minItems: null
                                    uniqueItems: null
                                    maxProperties: null
                                    minProperties: null
                                    required: null
                                    not: null
                                    properties: null
                                    additionalProperties: null
                                    nullable: null
                                    readOnly: null
                                    writeOnly: null
                                    example: null
                                    externalDocs: null
                                    deprecated: null
                                    discriminator: null
                                    xml: null
                                }
                            }]
                        }
                        examples: null
                        example: null
                        encoding: null
                    }}
                }
                links: null
                extensions: null
                $ref: null
            }, 200=class ApiResponse {
                description: OK
                headers: null
                content: class Content {
                    {application/json=class MediaType {
                        schema: class Schema {
                            type: null
                            format: null
                            $ref: #/components/schemas/ObjectDto
                            description: null
                            title: null
                            multipleOf: null
                            maximum: null
                            exclusiveMaximum: null
                            minimum: null
                            exclusiveMinimum: null
                            maxLength: null
                            minLength: null
                            pattern: null
                            maxItems: null
                            minItems: null
                            uniqueItems: null
                            maxProperties: null
                            minProperties: null
                            required: null
                            not: null
                            properties: null
                            additionalProperties: null
                            nullable: null
                            readOnly: null
                            writeOnly: null
                            example: null
                            externalDocs: null
                            deprecated: null
                            discriminator: null
                            xml: null
                        }
                        examples: null
                        example: null
                        encoding: null
                    }}
                }
                links: null
                extensions: null
                $ref: null
            }}
            extensions: null
        }

Как вы можете видеть, в ApiResponses есть пустой ApiResponse объект, который странным образом имеет ключ null, и сериализация затем завершается неудачей в MapSerializer.serialize():

// What is this _suppressNulls ?!
// _suppressableValue IS null, but is not suppressed
if ((_suppressableValue != null) || _suppressNulls) {
    serializeOptionalFields(value, gen, provider, _suppressableValue);
}

Джексона независимо от того, сколько Swagger Я использую аннотации (@Operation, добавляя @ApiResponse ...), этот null ApiResponse остается. Я не понимаю, откуда это происходит, особенно suppressNull влияет только на значения , а не ключи , согласно MapSerializer.serializeOptionalFields().

Как я могу удалить это null ApiResponse с ключом?

Ответы [ 2 ]

5 голосов
/ 01 мая 2020

Похоже, причина в том, что в обработчике исключений нет @ResponseStatus для @ ExceptionHandler.

Обходной путь должен быть добавлен, чтобы отобразить его в документации swagger.

Уже существует проблема, которая уже исправлена:

Исправление будет доступно в версии 1.3.8.

0 голосов
/ 01 мая 2020

Использование v1.3.4, кажется, работает нормально для меня. Я был на v1.3.3 и обновление до последней v1.3.7 сломало вещи.

Я думаю, виновником является исправление для https://github.com/springdoc/springdoc-openapi/issues/597

...