Skip to content

Parser incorrectly resolves response $refs, located in same file #2037

Closed
@ttrubinov

Description

@ttrubinov

I have $refs to schemas, that are located in the same file with endpoint in specification. Latest release of swagger-parser incorrectly resolves responses $refs

Generated OpenAPI should contain #/components/schemas/ before MyExampleResponseRef in path schema $refs, otherwise openapi-generator can't find the schema
However, 2.1.19 release of swagger-parser puts into $refs #MyExampleResponseRef, instead of #/components/schemas/MyExampleResponseRef, if this $ref is in the same file with endpoint

Example:

My example specification:
openapi.yaml:

openapi: 3.0.3
info:
  title: title
  version: LATEST

paths:
  /get:
    $ref: 'paths/get.yaml#/endpoint'

get.yaml:

endpoint:
  get:
    operationId: get
    requestBody:
      content:
        application/json:
          schema:
            $ref: '#/RequestBodyRef'
    responses:
      '200':
        content:
          application/json:
            schema:
              $ref: '#/ResponsesRef'

RequestBodyRef:
  type: string

ResponsesRef:
  type: string

OpenAPI output (result of openApiParser.readLocation(...)):

OpenAPI output
class OpenAPI {
    openapi: 3.0.3
    info: class Info {
        title: title
        description: null
        summary: null
        termsOfService: null
        contact: null
        license: null
        version: LATEST
    }
    externalDocs: null
    servers: [class Server {
        url: /
        description: null
        variables: null
    }]
    security: null
    tags: null
    paths: class Paths {
        {/get=class PathItem {
            summary: null
            description: null
            get: class Operation {
                tags: null
                summary: null
                description: null
                externalDocs: null
                operationId: get
                parameters: null
                requestBody: class RequestBody {
                    description: null
                    content: class Content {
                        {application/json=class MediaType {
                            schema: class Schema {
                                type: null
                                format: null
                                $ref: #/components/schemas/RequestBodyRef
                                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
                        }}
                    }
                    required: null
                }
                responses: class ApiResponses {
                    {200=class ApiResponse {
                        description: null
                        headers: null
                        content: class Content {
                            {application/json=class MediaType {
                                schema: class Schema {
                                    type: null
                                    format: null
                                    $ref: #/ResponsesRef
                                    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
                }
                callbacks: null
                deprecated: null
                security: null
                servers: null
            }
            put: null
            post: null
            delete: null
            options: null
            head: null
            patch: null
            trace: null
            servers: null
            parameters: null
            $ref: null
        }}
    }
    components: class Components {
        schemas: {ResponsesRef=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
            }
        }, RequestBodyRef=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
            }
        }}
        responses: null
        parameters: null
        examples: null
        requestBodies: null
        headers: null
        securitySchemes: null
        links: null
        callbacks: null
        pathItems: null
    }
}

As you can see above, ref to RequestBodyRef is correct, unlike ResponsesRef

And if I try to generate code with openapi-generator I got:

[main] WARN  o.o.codegen.utils.ModelUtils - Failed to get the schema name: #/ResponsesRef
[main] WARN  o.o.codegen.DefaultCodegen - Error obtaining the datatype from ref: #/ResponsesRef. Default to 'object'

With previous release of swagger-parser 2.1.18 everything works correct
Seems like PR #1994 made this bug (changing this file)

Openapi-generator uses swagger-parser 2.1.19 version in latest release, so this changes breaks our code generation

My code of OpenAPI generation:
OpenAPIV3Parser openApiParser = new OpenAPIV3Parser();
ParseOptions options = new ParseOptions();
options.setResolve(true);
options.setResolveCombinators(true);
options.setAllowEmptyString(true);
options.setValidateInternalRefs(true);
options.setInferSchemaType(true);
SwaggerParseResult parseResult =
        openApiParser.readLocation("my_specification_location", null, options);
OpenAPI openAPI = parseResult.getOpenAPI();

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions