📖 2 min read (~ 500 words).

When the scanner emits a type

codescan does not emit a definition for every type it can see. A named type reaches the spec when either of these holds:

  • it is reachable — referenced (directly or transitively) from an operation, parameter, response, or another emitted model; or
  • it is registered — annotated swagger:model, which (with Options.ScanModels) publishes it even when nothing references it.

A type that is neither reachable nor registered is simply absent — the scanner never invents it. The package below has one of each case:

// Order is reached only through Cart below. A referenced named type is emitted
// as a $ref target even without swagger:model.
type Order struct {
	// ID is the order identifier.
	ID string `json:"id"`
}

// Cart references Order, so Order gets a definition and the field a $ref.
//
// swagger:model
type Cart struct {
	// Order is the referenced (and therefore emitted) nested model.
	Order Order `json:"order"`
}

// Standalone is never referenced, but swagger:model together with ScanModels
// publishes it anyway.
//
// swagger:model
type Standalone struct {
	// Label is a free-text label.
	Label string `json:"label"`
}

// Orphan is never referenced and carries no swagger:model — the scanner does
// not invent it, so it never reaches the spec.
type Orphan struct {
	// Secret is internal.
	Secret string `json:"secret"`
}

Full source: docs/examples/shaping/discovery/discovery.go

Scanned with ScanModels: true, the definitions are:

{
  "Cart": {
    "type": "object",
    "title": "Cart references Order, so Order gets a definition and the field a $ref.",
    "properties": {
      "order": {
        "$ref": "#/definitions/Order"
      }
    },
    "x-go-package": "github.com/go-openapi/codescan/docs/examples/shaping/discovery"
  },
  "Order": {
    "description": "Order is reached only through Cart below. A referenced named type is emitted\nas a $ref target even without swagger:model.",
    "type": "object",
    "properties": {
      "id": {
        "description": "ID is the order identifier.",
        "type": "string",
        "x-go-name": "ID"
      }
    },
    "x-go-package": "github.com/go-openapi/codescan/docs/examples/shaping/discovery"
  },
  "Standalone": {
    "description": "Standalone is never referenced, but swagger:model together with ScanModels\npublishes it anyway.",
    "type": "object",
    "properties": {
      "label": {
        "description": "Label is a free-text label.",
        "type": "string",
        "x-go-name": "Label"
      }
    },
    "x-go-package": "github.com/go-openapi/codescan/docs/examples/shaping/discovery"
  }
}

Full source: docs/examples/shaping/discovery/testdata/definitions.json

  • Cart — a swagger:model root.
  • Order — has no swagger:model, yet it is emitted (as a $ref target) because Cart references it. You do not need to annotate every nested type.
  • Standalone — a swagger:model that nothing references; ScanModels publishes it anyway.
  • Orphan — neither referenced nor annotated, so it never appears.
Info

If a model is missing from your spec, it is almost always unreachable: no operation/parameter/response/model leads to it. Either reference it, or annotate it swagger:model and scan with ScanModels.