swagger-api / swagger-parser

Swagger Spec to Java POJOs
http://swagger.io
Apache License 2.0
773 stars 526 forks source link

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

Closed ttrubinov closed 5 months ago

ttrubinov commented 5 months ago

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 commented 5 months ago

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