Skip to content

Model generation $ref-utilising components not consumer friendly #1362

@percivalalb

Description

@percivalalb

In larger OpenAPI specs it is useful to split up components into multiple files and use $ref to "stitch" the spec together. This doesn't quite work when generating models, full example:

Example Spec

  1. schemas/record.yaml
type: object
required:
  - id
properties:
  id:
    type: number

2.1 schemas/records.yaml

type: array
items:
  $ref: './record.yaml'
  1. api.yaml
openapi: "3.0.0"
info:
  version: 1.0.0
  title: Ref Example
paths:
  /records:
    get:
      operationId: getRecords
      responses:
        200:
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Records'
  /record:
    get:
      operationId: getRecord
      responses:
        200:
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Record'      
components:
  schemas:
    Record:
      $ref: './schemas/record.yaml'
    Records:
      $ref: './schemas/records.yaml'

The go generated code doesn't recongise the array item definition is the same as the Record definition and so doesn't reference Record from Records. Instead it usings an anonymous type which makes it annoying to use. Ideally it should be type Records = []Record

// Record defines model for Record.
type Record struct {
	Id float32 `json:"id"`
}

// Records defines model for Records.
type Records = []struct {
	Id float32 `json:"id"`
}

Alternative Approach

Changing file 2. to .... has a different problem.
2.2 schemas/records.yaml

type: array
items:
  $ref: '../api.yaml#/components/schemas/Record'
$ go generate ./...
error generating code: error generating type definitions: error generating Go types for component schemas: error converting Schema Records to Go type: error resolving primitive type: error generating type for array: error turning reference (../api.yaml#/components/schemas/Record) into a Go type: unrecognized external reference '../api.yaml'; please provide the known import for this reference using option --import-mapping
exit status 1
doc.go:6: running "go": exit status 1

However the API component in the "external reference" isn't actually external. It is part of this API spec so using import-mapping doesn't make sense or actually work, as the go type is generated in the same file not in another package.

Changing 2. to ... to remove the external reference does remove the use of an anonymous type though isn't techincally valid OpenAPI (even though the code generation does seem to work - I believe it fails on the first run but then succeeds therafter).
2.3 schemas/records.yaml

type: array
items:
  $ref: '#/components/schemas/Record'

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:external-refsAnything related to external references (referencing other file(s) within a spec)bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions