Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
ttrubinov opened this issue Jan 12, 2024 · 1 comment
Closed

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

ttrubinov opened this issue Jan 12, 2024 · 1 comment
Assignees

Comments

@ttrubinov
Copy link

ttrubinov commented Jan 12, 2024

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();
@gracekarina
Copy link
Contributor

fix by: https://github.com/swagger-api/swagger-parser/pull/2052/files

gracekarina added a commit that referenced this issue Feb 5, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants