github.com/go-swagger/go-swagger@v0.31.0/docs/reference/models/schemas.md (about)

     1  ---
     2  title: Swagger schema generation rules
     3  date: 2023-01-01T01:01:01-08:00
     4  draft: true
     5  ---
     6  # Schema generation rules
     7  
     8  Lots of the work carried out by go-swagger is to generate models, which can have all kinds of rules like polymorphism and
     9  validations. Go-swagger models are the go data structures used for serialization and validation.
    10  
    11  Of course none of this is possible without a set of rules and trade-offs.
    12  
    13  ### About schemas
    14  
    15  A schema is a data structure specified in a Swagger document. Loosely speaking, a swagger schema corresponds to
    16  a JSONSchema-draft4 schema (see [differences](#swagger-vs-jsonschema) below).
    17  For each schema, `go-swagger` will generate one or more model types in go.
    18  
    19  > **NOTE**: Swagger makes a distinction between schemas and "simple schemas".
    20  > We use simple schemas to describe parameters and headers for operations.
    21  > Simple schemas are supported by `go-swagger` (including validation), but are not rendered as standalone models.
    22  > Rather, simple schema structures and validation methods are generated with the operation they are attached to.
    23  >
    24  > Models are dedicated to the description of Swagger schemas, which are described as a parameter body, a response or a
    25  > spec definition.
    26  
    27  #### Interfaces
    28  
    29  The generated models implements:
    30  
    31  - a serialization interface
    32    - `MarshalJSON()`, `UnmarshalJSON()`:
    33      - standard structures use JSON decoder tags (serialization tags are customizable)
    34      - composed and extensible structures use custom marshalers (`allOf`, `additionalProperties`, tuples and polymorphic types)
    35    - `MarshalBinary()`, `UnmarshalBinary()` interfaces (`encoding/BinaryMarshaler`, `encoding/BinaryUnmarshaler`),
    36    which may use the fast [`mailru/easyjson`][easy-json] package
    37  - a validation interface ([`go-openapi/runtime/Validatable`][Validatable]), with a `Validate(strfmt.Registry) error` method
    38  
    39  Validation methods are wired at generation time, and rely mostly on native types: this makes validation faster than a
    40  dynamic general purpose JSON schema validator.
    41  
    42  Example of a generated structure:
    43  ```golang
    44  // Principal principal
    45  // swagger:model principal
    46  type Principal struct {
    47  
    48  	// name
    49  	Name string `json:"name,omitempty"`
    50  
    51  	// roles
    52  	Roles []string `json:"roles"`
    53  }
    54  ```
    55  
    56  > **NOTE**: if you are looking for a **dynamic**, fully JSONSchema compliant, general purpose validator,
    57  > the [`go-openapi/validate`][validate] package
    58  > is what you want. It is fully tested against the JSONSchema-Test-Suite (supports JSON-schema-draft4).
    59  > See a working example [here][validate-json].
    60  
    61  #### Mapping patterns
    62  
    63  The general idea is that you should rarely see `interface{}` in the generated code:
    64  you get a complete representation of a swagger document in somewhat idiomatic go.
    65  
    66  There is set of mapping patterns that are applied to transform a spec into go types:
    67  
    68  * definition of primitive => type alias/name
    69  * definition of array => type alias/name
    70  * definition of map => type alias/name
    71  * definition of object with properties => struct
    72  * definition of $ref => type alias/name
    73  * object with only additional properties => map[string]T
    74  * object with additional properties and properties => custom serializer
    75  * schema with schema array in items => tuple (struct with properties, custom serializer)
    76  * schema with all of => struct
    77  * all of schema with ref => embedded value
    78  * all of schema with properties => properties are included in struct
    79  * adding an all of schema with just `x-isnullable`: true or `x-nullable`: true turns
    80  the schema into a pointer when there are only other extension properties provided
    81  * additional items in tuples =>
    82  JSONSchema and by extension swagger allow for items that have a fixed size array
    83  with schema's describing the items at each index. This can be combined with additional items
    84  to form some kind of tuple with varargs.
    85  To map this to go it creates a struct that has fixed names and a custom json serializer.
    86  
    87  #### Minimal use of go's reflection
    88  
    89  Generated models uses _no reflection_ except for `enum` and `required` validations. This makes validation faster.
    90  
    91  #### Doc strings
    92  
    93  All documentation items provided by the spec are integrated as godoc-friendly comments in the
    94  generated source. You may look at how a trivial example is rendered [here][go-doc-model].
    95  
    96  The code that is generated also gets the same doc comments that are used by the scanner
    97  to generate a spec from go code (e.g. comments like `// swagger:xxx`).
    98  So that after generation you should be able to reverse-generate a spec from the code that was generated by your spec.
    99  It should be equivalent to the original spec but might miss some default values and examples.
   100  
   101  #### Types reusability
   102  
   103  Models can be generated independently from other components of your API.
   104  Internal model structures may thus be safely regenerated if the contract at your endpoints does not change.
   105  
   106  ##### Reusing previous generations
   107  
   108  Previously generated models can be reused when constructing a new API server or client (e.g. using `swagger generate server --model=[my existing package]`).
   109  
   110  The generator makes every effort to keep the go code readable, idiomatic and commented: models may thus be manually customized or extended.
   111  Such customized types may be later on reused in other specs, using the `x-go-type` extension.
   112  
   113  
   114  ### Swagger vs JSONSchema
   115  
   116  A Swagger 2.0 schema corresponds by and large to a JSON-schema-draft4. However, there are some substantial differences (see [swagger]):
   117  
   118  In JSONSchema, but _not_ in Swagger 2.0:
   119  
   120  - `anyOf`, `oneOf` and `not` constructs are not supported (this is for OpenAPI 3)
   121  - the `null` type is not supported (the `nullable` keyword is defined in OpenAPI 3)
   122  - `additionalItems` are not supported (go-swagger does support it)
   123  - `patternProperties` are not supported
   124  - `dependencies` are not supported
   125  - multiple types, defined as `type: [ ... ]` are not supported
   126  
   127  Conversely, what we have in Swagger 2.0, but _not_ in JSON-schema:
   128  
   129  - the `discriminator` attribute controls polymorphism ([see below](#polymorphic-types))
   130  - properties may be given a [`readOnly` attribute][read-only] (same as in JSONSchema-draft7)
   131  - `array` types **must** have an `items` restriction
   132  - `format` supports more values for strings and numbers
   133  
   134  Other minor differences:
   135  
   136  - `default` values **must** validate their schema
   137  - types `array` **must** have an `items` specification
   138  - extensions may be specified as special `x-...` annotations. Go-swagger defines [some custom tags](#custom-extensions) to customize generated code.
   139  - other available attributes: `example`, `xml` and `externalDocs`
   140  
   141  > **NOTE**: `example` and `externalDocs` do not currently influence models generation.
   142  
   143  ### Go-swagger vs Swagger
   144  
   145  go-swagger models implements _almost_ all Swagger 2.0 schema features.
   146  
   147  We also wanted to support as much JSONSchema features as possible: the model generator may be used independently
   148  to generate data structures using the Swagger specification as a serialization description language.
   149  
   150  There are some small differences or implementation details to be aware of.
   151  
   152  |   Feature                             | JSON-schema-draft4 |  Swagger 2.0 |  go-swagger |   Comment |
   153  |---                                    |---                 |---           |---          |---        |
   154  | `"format"`                            |   Y| Y    | Y      | Formats are provided by the extensible [`go-openapi/strfmt` package][strfmt]. See also [here](#formatted-types)|
   155  | `"additionalProperties": {schema}`    |   Y| Y    | Y      | Rendered as `map[string]T`                           |
   156  | `"additionalProperties": boolean`     |   Y| Y    | partial| Rendered as `map[string]interface{}`                           |
   157  | `"additionalItems": {schema}`         |   Y| **N**| Y      | Rendered with [tuple models](#tuples-and-additional-items)|
   158  | `"additionalItems": boolean`          |   Y| **N**| partial| See [extensible types](#extensible-types)             |
   159  | empty object: `{ "type": "object"}`   |   Y| Y    | Y      | Rendered as `interface{}` (anything) rather than `map[string]inferface{}` (any JSON object, e.g. not arrays)|
   160  | `"pattern"`                           |   Y| Y    | partial| Speed for strictness trade-off: support go regexp, which slighty differ from JSONSchema ECMA regexp (e.g does not support backtracking)|
   161  |  large number, arbitrary precision    |   Y| **N**| N      |    |
   162  | `"readOnly"`                          |   N| Y    | Y      |    |
   163  | `"type": [ "object", ... ]`           |   Y| N    | N      | JSONSchema multiple types are not supported: use Swagger polymorphism instead|
   164  | implicit type from values in `enum`   |   Y| ?    | N      | As of v0.15, when the type is empty, the object is rendered as `interface{}` and the `enum` constraint is ignored|
   165  | tuple `type: "array" items:[...]      |   Y| Y    | partial| As of v0.15, incomplete tuples and tuples with array validation are not properly validated|
   166  
   167  
   168  JSONSchema defaults to `"additionalProperties": true`, `go-swagger` defaults to ignoring extra properties. Same for `additionalItems`.
   169  
   170  When`"additionalProperties": false` (resp. `"additionalItems": false`), uwanted properties (resp. items) do not invalidate data
   171  but they are not kept in the model.
   172  
   173  This is the default if `additionalProperties` (resp. `additionalItems`) is not provided.
   174  It is an optimization as it makes the code simpler (and faster) for most use cases.
   175  Explicitly specifying `true` will produce models that retain those additional properties (resp. items).
   176  
   177  ### Known limitations with go-swagger models
   178  
   179  Recap as of release `>0.26`:
   180  
   181  - re [JSON-schema-draft4][json-schema]
   182  
   183    - `"additionalProperties": false`, `"additionalItems": false` do not invalidate data with extra properties. We trade strictness for speed and
   184      truncate unwanted properties or items without further validation.
   185    - the generation flag `--strict-additional-properties` invalidates data with extra properties when `"additionalProperties": false`
   186    - when `enum` values cannot be marshalled into their schema, a runtime panic occurs - the `go-openapi/validate` package does not yet detect this situation
   187    - `patternProperties` and `dependencies`are not supported
   188    - use of `additionalItems` requires the `--skip-validation` flag (`go-openapi/validate` is strict regarding Swagger specification)
   189    - JSONSchema defaults to the `"additionalProperties": true`, `go-swagger` defaults to ignoring extra properties. Same for `additionalItems`.
   190    - array validations (`minItems`, etc.) are not yet supported for tuples, as of v0.15
   191    - objects with no properties and no additional properties schema have no validation at all (e.g. passing an array is not invalid) (rendered as `interface{}`)
   192    - `null` JSON type: the `null` type is not supported by Swagger - use of the `x-nullable` extension makes `null` values valid
   193    (notice that combining the use of `required` and `x-nullable` is not fully JSONSchema compliant - see [below](#nullability))
   194  
   195  ### Custom extensions
   196  
   197  Model generation may be altered with the following extensions:
   198  
   199  - `x-go-name: "string"`: give explicit type name to the generated model
   200  - `x-go-custom-tag: "string"`: add serialization tags to an object property (see [Customizing struct tags](#customizing-struct-tags))
   201  - `x-nullable: true|false` (or equivalently `x-is-nullable:true|false`): accepts null values (i.e. rendered as a pointer)
   202  - `x-go-type: "string"`: explicitly reuse an already available go type
   203  - `x-class: "string"`: give explicit polymorphic class name in discriminator
   204  - `x-order: number`: indicates explicit generation ordering for schemas (e.g. models, properties, allOf, ...)
   205  - `x-omitempty: true|false`: force the omitempty modifier in struct json and xml tags
   206  - `x-go-json-string: true:false`: force the string modifier in struct json tags
   207  
   208  ### Primitive types
   209  
   210  Swagger types are rendered as follows by `go-swagger`:
   211  
   212  | Swagger type                | go type  |
   213  |-----------------------------|----------|
   214  | `string` (no format)        | `string` |
   215  | `boolean`                   | `bool`   |
   216  | `number`                    | `float64`|
   217  | `number format double`      | `float64`|
   218  | `number format float`       | `float32`|
   219  | `integer`                   | `int64`  |
   220  | `integer format int64`      | `int64`  |
   221  | `integer format int32`      | `int32`  |
   222  | `integer format uint64`     | `uint64` |
   223  | `integer format uint32`     | `uint32` |
   224  | `file`                      | `io.ReadCloser`(server) or `io.Writer` (client)|
   225  | `string format binary`      | `io.ReadCloser`or `io.Writer`|
   226  | `string` with other formats | corresponding type exported by `go-openapi/strfmt` |
   227  
   228  The `file` type is exposed as a `io.ReadCloser` (or `io.Writer`) interface. The actual implementation in a
   229  runtime server or client is provided by the [`go-openapi/runtime/File` type][File].
   230  
   231  ### Formatted types
   232  
   233  The `go-openapi/strfmt` packages provides a number of predefined "formats" for JSON string types.
   234  The full list of formats supported by this package is [here][all-formats]
   235  
   236  ### Nullability
   237  
   238  Here are the rules that turn something into a pointer.
   239  * structs
   240  * `x-nullable`, `x-isnullable`: explicit override to accept null values (otherwise not accepted by Swagger)
   241  * required property
   242  * extending with `allOf` a schema with another schema with just `x-nullable` (or other extensions,
   243  but no new properties) turns the schema into a pointer
   244  
   245  Primitive types (number, bool and string) are turned into pointers whenever:
   246  * we need to validate valid zero values vs unset (i.e. the zero value is explicitly checked against validation)
   247  
   248  Examples:
   249  ```yaml
   250  definitions:
   251    myInteger:
   252      type: integer
   253      minimum: 0
   254    myString:
   255      type: string
   256      minLength: 0
   257  ```
   258  
   259  Yields:
   260  ```go
   261  type MyInteger *int64
   262  ...
   263  type MyString *string
   264  ```
   265  
   266  Notice that the following equivalent does not produce a pointer:
   267  ```yaml
   268  definitions:
   269    myInteger:
   270      type: integer
   271      format: uint64
   272  ```
   273  
   274  > NOTE: read-only properties are not rendered as pointers.
   275  
   276  API developers may use the conversion utilities provided by the `go-openapi/swag` and `go-openapi/strfmt/conv` packages
   277  to manipulate pointers more easily.
   278  
   279  > **Known limitations**:
   280  > pointers are used to distinguish in golang a zero value from no value set.
   281  >
   282  > This design comes with some shortcomings:
   283  >
   284  > - it is built around the validation use case.
   285  > In the general case it is not possible to know if a value has been set
   286  > to a zero value when the type is not a pointer. In cases where this is
   287  > important, use the `x-nullable` extension
   288  > - using `null` as a proxy for unset, makes uneasy the explicit use of the JSON `null` type
   289  > Swagger APIs are not supposed to carry `null` values.
   290  > `go-swagger` generated APIs can, using the `x-nullable` extension, and it is then not possible
   291  > to distinguish a field explicitly set to `null` from an unset field
   292  >
   293  > An alternate design has been experimented but not released. For those interested in pushing forward this project again,
   294  > see [this pull request][lifting-pointers]
   295  
   296  #### Common use cases
   297  
   298  You don't always have to resort to pointers to figure out whether a value is empty.
   299  
   300  * The idiomatic way to check for a null/empty string is: `minLength: 1`
   301  
   302  ### Validation
   303  
   304  All produced models implement the [Validatable] interface.
   305  
   306  Exceptions:
   307  - `file` types do not support validation (however generated operations may check the `maxLength` of a file)
   308  - empty schemas (`any` type, rendered as `interface{}`) do not support validation
   309  
   310  Therefore, type aliases constructed on either a swagger `file` or an empty schema does not implement this interface.
   311  
   312  Validation errors:
   313  - Returned errors are supported by the `go-openapi/errors/Error` type, which supports errors codes and composite errors.
   314  
   315  Validation stops assessing errors down to the property level and does not continue digging all nested strutures as soon
   316  as an error is found.
   317  
   318  ### Type aliasing
   319  
   320  A definition may create an _aliased_ type like this:
   321  
   322  ```yaml
   323  definitions:
   324    myDate:
   325      type: string
   326      format: date
   327  ```
   328  
   329  Rendered as:
   330  ```go
   331  type MyDate strfmt.Date
   332  ```
   333  
   334  Notice that setting `x-nullable: true` in such an alias will not render the type itself into a pointer, but rather,
   335  all containers of his type will use it as a pointer.
   336  
   337  Example:
   338  ```yaml
   339  definitions:
   340    myDate:
   341      type: string
   342      format: date
   343      x-nullable: true
   344    anArrayOfDates:
   345      type: array
   346      items:
   347        $ref: '#/definitions/myDate'
   348  ```
   349  
   350  Yields:
   351  ```go
   352  type MyDate strfmt.Date
   353  ...
   354  type AnArrayOfDates []*MyDate
   355  ```
   356  
   357  Realiasing
   358  
   359  Given the above definitions, we add:
   360  
   361  ```yaml
   362    ...
   363    herDate:
   364      $ref: #/definitions/myDate
   365    hisDate:
   366      $ref: #/definitions/herDate
   367  ```
   368  
   369  Rendered as (requires go1.9+):
   370  ```go
   371  type HerDate = MyDate
   372  ```
   373  
   374  ```go
   375  type HisDate = HerDate
   376  ```
   377  
   378  ### Extensible types
   379  
   380  ##### Objects and additional properties
   381  
   382  Additional properties in a JSON object are represented in a go struct by `map[string]T`.
   383  
   384  Examples:
   385  
   386  ```yaml
   387  definitions:
   388    extensibleObject:
   389      properties:
   390        prop1:
   391          type:  integer
   392      additionalProperties:
   393        type: string
   394        format: date
   395  ```
   396  
   397  Is rendered as:
   398  ```golang
   399  type ExtensibleObject struct {
   400      Prop1 int64
   401      ExtensibleObjectProperties map[string]strfmt.Date
   402  }
   403  ```
   404  
   405  If there is no restriction on the additional properties:
   406  
   407  ```yaml
   408  definitions:
   409    extensibleObject:
   410      type: object
   411      properties:
   412        prop1:
   413          type: integer
   414      additionalProperties: true
   415  ```
   416  
   417  We get:
   418  ```golang
   419  type ExtensibleObject struct {
   420      Prop1 int64
   421      ExtensibleObjectProperties map[string]interface{}
   422  }
   423  ```
   424  
   425  ##### Tuples and additional items
   426  
   427  A tuple is rendered as a structure with a property for each element of the tuple.
   428  
   429  Example:
   430  ```yaml
   431  definitions:
   432    tuple:
   433      type: array
   434      items:
   435      - type: integer
   436      - type: string
   437      - type: string
   438        format: uuid
   439  ```
   440  
   441  Gives:
   442  ```golang
   443  type Tuple struct {
   444      P0 *int64
   445      P1 *string
   446      P2 *strfmt.UUID
   447  }
   448  ```
   449  
   450  If we specify additional items as in:
   451  ```yaml
   452  definitions:
   453    extensibleTuple:
   454      type: array
   455      items:
   456      - type: integer
   457      - type: string
   458      - type: string
   459        format: uuid
   460      additionalItems:
   461      - type: number
   462  ```
   463  Gives:
   464  ```golang
   465  type ExtensibleTuple struct {
   466      P0 *int64
   467      P1 *string
   468      P2 *strfmt.UUID
   469      ExtensibleTupleItems []float64
   470  }
   471  ```
   472  
   473  > **NOTE**: currently the P0, P1, ... names are not customizable.
   474  
   475  ### Polymorphic types
   476  
   477  Polymorphic types are swagger's flavor for inheritance (aka _hierarchized composition_...).
   478  The use of the `discriminator` keyword gives a special meaning to `allOf` compositions.
   479  
   480  #### Base types
   481  Whenever the special attribute `discriminator` is used, this means this object definition is
   482  a base type, to be used to extend other types, or subtypes.
   483  
   484  The discriminator property indicates which subtype is used whenever an instance of the base type is found.
   485  The discriminator's possible values are the names of the subtypes (no aliasing is supported in Swagger 2.0).
   486  
   487  > **NOTE**: the discriminator is a `required` property with `"type": "string"`.
   488  > No validation attached to this property, save `required`, will be honored, as
   489  > a discriminator property is implicitly an `enum` with all the subtype names found in the spec.
   490  
   491  The base type must be a JSON-schema object (it has at least one property, the discriminator).
   492  It may define other properties than the discriminator. Like `name` in this example.
   493  
   494  Example:
   495  ```yaml
   496    Pet:
   497      type: object
   498      discriminator: petType
   499      properties:
   500        name:
   501          type: string
   502        petType:
   503          type: string
   504      required:
   505      - name
   506      - petType
   507  ```
   508  
   509  A base type is rendered as an interface, with getter/setter funcs on all attributes.
   510  
   511  ```go
   512  // Pet pet
   513  // swagger:discriminator Pet petType
   514  type Pet interface {
   515  	runtime.Validatable
   516  
   517  	// name
   518  	// Required: true
   519  	Name() *string
   520  	SetName(*string)
   521  
   522  	// pet type
   523  	// Required: true
   524  	PetType() string
   525  	SetPetType(string)
   526  }
   527  ```
   528  
   529  > **NOTE**: an unexported reference concrete type is also generated, but not currently used by models.
   530  
   531  #### Subtypes
   532  
   533  A subtype _extends_ a base type. It is defined by composing the base type with an `allOf` construct.
   534  All subtypes implement the interface of their base type. So in this examples, all instances of `Dog` may pretend
   535  to be a `Pet`.
   536  
   537  Example:
   538  ```yaml
   539    Dog:
   540      type: object
   541      description: A representation of a dog
   542      allOf:
   543      - $ref: '#/definitions/Pet'
   544      - properties:
   545          packSize:
   546            type: integer
   547            format: int32
   548            description: the size of the pack the dog is from
   549            default: 0
   550            minimum: 0
   551        required:
   552        - packSize
   553  ```
   554  
   555  Yields:
   556  ```go
   557  // Dog A representation of a dog
   558  // swagger:model Dog
   559  type Dog struct {
   560  	nameField *string
   561  
   562  	// the size of the pack the dog is from
   563  	// Required: true
   564  	// Minimum: 0
   565  	PackSize *int32 `json:"packSize"`
   566  }
   567  
   568  // Name gets the name of this subtype
   569  func (m *Dog) Name() *string {
   570  	return m.nameField
   571  }
   572  
   573  // SetName sets the name of this subtype
   574  func (m *Dog) SetName(val *string) {
   575  	m.nameField = val
   576  }
   577  
   578  // PetType gets the pet type of this subtype
   579  func (m *Dog) PetType() string {
   580  	return "Dog"
   581  }
   582  
   583  // SetPetType sets the pet type of this subtype
   584  func (m *Dog) SetPetType(val string) {
   585  
   586  }
   587  ```
   588  
   589  Notice the unexported fields which correspond to the description of the base type.
   590  The properties of the base type are available with getter/setter functions.
   591  
   592  > **NOTE**: if you expand your spec, the `allOf` semantics are lost.
   593  > Do not expand specs with polymorphic types for code generation.
   594  
   595  You may define several such derived types.
   596  
   597  Example:
   598  ```yaml
   599    cat:
   600      type: object
   601      description: A representation of a cat
   602      allOf:
   603      - $ref: '#/definitions/Pet'
   604      - properties:
   605          huntingSkill:
   606            type: string
   607            description: The measured skill for hunting
   608            default: lazy
   609            enum:
   610            - clueless
   611            - lazy
   612            - adventurous
   613            - aggressive
   614        required:
   615        - huntingSkill
   616  ```
   617  
   618  ```go
   619  // Cat A representation of a cat
   620  // swagger:model cat
   621  type Cat struct {
   622  	nameField *string
   623  
   624  	// The measured skill for hunting
   625  	// Required: true
   626  	// Enum: [clueless lazy adventurous aggressive]
   627  	HuntingSkill *string `json:"huntingSkill"`
   628  }
   629  
   630  // Name gets the name of this subtype
   631  func (m *Cat) Name() *string {
   632  	return m.nameField
   633  }
   634  
   635  // SetName sets the name of this subtype
   636  func (m *Cat) SetName(val *string) {
   637  	m.nameField = val
   638  }
   639  
   640  // PetType gets the pet type of this subtype
   641  func (m *Cat) PetType() string {
   642  	return "cat"
   643  }
   644  
   645  // SetPetType sets the pet type of this subtype
   646  func (m *Cat) SetPetType(val string) {
   647  
   648  }
   649  ```
   650  
   651  Notice that the value of the discriminator field is case sensitive, e.g. `"Dog"` and `"cat"` above.
   652  
   653  #### Type composition
   654  
   655  Base types and subtypes may be used in other constructs. While subtypes are mostly handled like ordinary objects,
   656  there are special provisions taken to generate new types composing base types.
   657  
   658  Example:
   659  ```yaml
   660    Kennel:
   661      type: object
   662      required:
   663        - pets
   664      properties:
   665        id:
   666          type: integer
   667          format: int64
   668        pets:          # <-- this may contain Cats and Dogs
   669          type: array
   670          items:
   671            $ref: "#/definitions/Pet"
   672  ```
   673  
   674  Yields:
   675  ```go
   676  // Kennel kennel
   677  // swagger:model Kennel
   678  type Kennel struct {
   679  
   680  	// id
   681  	ID int64 `json:"id,omitempty"`
   682  
   683  	petsField []Pet
   684  }
   685  
   686  // Pets gets the pets of this base type
   687  func (m *Kennel) Pets() []Pet {
   688  	return m.petsField
   689  }
   690  
   691  // SetPets sets the pets of this base type
   692  func (m *Kennel) SetPets(val []Pet) {
   693  	m.petsField = val
   694  }
   695  ```
   696  
   697  > **NOTE**: this representation with unexported fields for references to base types might be subject to change in
   698  > the future, as it is not consistent in all cases. If you are intested to participate this design work,
   699  > feel free to comment and express your views [here](https://github.com/go-swagger/go-swagger/issues/232).
   700  
   701  #### Factories for base types
   702  
   703  Subtypes and composed types have custom [un]marshallers.
   704  
   705  Unmarshalling a base type is not carried through the standard MarshalJSON()/UnmarshalJSON() pair, but with
   706  factories created for each base type.
   707  
   708  Example:
   709  ```go
   710  // UnmarshalPet unmarshals polymorphic Pet
   711  func UnmarshalPet(reader io.Reader, consumer runtime.Consumer) (Pet, error)
   712  
   713  // UnmarshalPetSlice unmarshals polymorphic slices of Pet
   714  func UnmarshalPetSlice(reader io.Reader, consumer runtime.Consumer) ([]Pet, error)
   715  ```
   716  
   717  Note that the marshalling of a base type into JSON is processed naturally, so there is no need for a special function.
   718  
   719  > **Known limitations**:
   720  > As of v0.15, there are still some known limitations:
   721  >
   722  > - Unmarshalling maps of base types is not supported at the moment (e.g. `UnmarshalPetMap()` factory)
   723  > - More complex constructs like `[][]Pet`, `[]map[string]Pet` are not supported yet
   724  > - composing tuples containing base types is not supported yet
   725  
   726  ### Serialization interfaces
   727  
   728  <!--
   729  
   730  JSON
   731  
   732  XML
   733  -->
   734  
   735  ##### Custom serializers
   736  
   737  Tags are generally sufficient to provide proper JSON marshalling capabilities.
   738  
   739  Models define some custom [un]marshallers in the following situations:
   740  - tuples: array elements are dispatched in the tuple's struct
   741  - additionalProperties: additional content is dispatched in the `map[string]...`
   742  - subtypes of base types
   743  - types composed of base types
   744  - aliases on formatted types when the underlying type is not string (e.g. Date, Datetime)
   745  
   746  <!--
   747  ##### [Un]MarshalBinary interfaces
   748  
   749  TODO
   750  -->
   751  
   752  <!-- References -->
   753  
   754  ##### External types
   755  
   756  External types refer to custom type definitions, short-circuiting the use of generated models.
   757  
   758  This is helpful for use-cases when custom marshaling or validation is needed.
   759  
   760  Models may also be generated once, customized manually, then reused in spec as external types.
   761  
   762  The extension annotation to declare an external type is `x-go-type`.
   763  
   764  A complete example is provided [here](https://github.com/go-swagger/go-swagger/tree/master/examples/external-types)
   765  to illustrate the different capabilities to inject custom types.
   766  
   767  
   768  Examples:
   769  
   770  External types are typically used in top-level model definitions, like so:
   771  
   772  ```yaml
   773  definitions:
   774    myType:
   775      type: object
   776      x-go-type:
   777        type: MyExternalType                          # <- abide by go conventions! The type must be exported
   778        import:
   779          package: github.com/example/models/custom     # <- use fully qualified package names
   780  ```
   781  
   782  Such definitions do not produce any generated model.
   783  
   784  References in the generated code to this type will produce code like this:
   785  
   786  ```go
   787  custom.MyExternalType
   788  ```
   789  
   790  If no package is provided, it defaults to the models package indicated for codegen:
   791  ```yaml
   792  definitions:
   793    generatedType:
   794      type: array
   795      items:
   796        $ref: '#/definitions/myType'
   797  
   798    myType:
   799      type: object
   800      x-go-type:
   801        type: MyExternalType
   802  ```
   803  
   804  ```sh
   805  swagger generate models --model-package custom --target ./codegen
   806  
   807  ls ./codegen/custom   # <- myType is NOT GENERATED
   808  cat ./codegen/custom/generated_type.go
   809  ```
   810  
   811  ```go
   812  package custom
   813  
   814  type GeneratedType []MyType
   815  ```
   816  
   817  External types may also be injected at lower schema levels:
   818  
   819  ```yaml
   820  definitions:
   821    MyType:
   822      type: array
   823      items:
   824        type: string
   825        x-go-type:
   826          type: MyExternalString
   827          import:
   828            package: github.com/example/models/custom
   829  ```
   830  or:
   831  ```yaml
   832    MyObject:
   833      type: object
   834      properties:
   835        p1:
   836          x-go-type:
   837            type: RawMessage
   838            import:
   839              package: encoding/json
   840            hints:
   841              kind: interface
   842  ```
   843  
   844  This also works for inlined types defined at the operation level:
   845  
   846  ```yaml
   847    parameters:
   848    - in: body
   849      name: corpus
   850      schema:
   851        type: object
   852        x-go-type:
   853          type: MyExternalStruct
   854          import:
   855            package: github.com/example/models/custom
   856  ```
   857  
   858  > **NOTE**: when defining inline arrays or maps, you should know that the external type is
   859  > not considered nullable by default.
   860  >
   861  > Therefore, unless you explicitly hint the generator to consider it nullable, you'll
   862  > get constructs such as `[]external.MyType` or `map[string]external.MyType` instead of `[]*external.MyType`
   863  > and `map[string]*external.MyType` respectively. You can use the `nullable` hint or the `x-nullable` extension
   864  > to control this behavior.
   865  
   866  ###### Known limitations
   867  
   868  * External types only apply to schema objects. Simple swagger types
   869    used in operations for query or path parameters or for response headers
   870    cannot be externalized at this moment.
   871  
   872  * Inlined external types cannot be declared inside polymorphic types (discriminated types).
   873  
   874  * Inlined external types cannot be declared as embedded. Only top-level definitions are supported.
   875  
   876  
   877  ###### External package aliasing
   878  
   879  
   880  The following example replaces all references to `myModel` by `github.com/example/models/MyCustomModel`.
   881  
   882  Example:
   883  
   884  ```yaml
   885  definitions:
   886    myModel:
   887      type: object
   888      x-go-type:
   889        type: MyCustomModel
   890        import:
   891          package: github.com/example/models
   892  ```
   893  
   894  Note that the external model must implement the `github.com/go-openapi/runtime.Validatable` interface: it must know how to validate a schema.
   895  No model is generated for this definition.
   896  
   897  External packages may be imported with an alias, like so:
   898  
   899  ```yaml
   900    parameters:
   901      in: body
   902      schema:
   903        type: object
   904        x-go-type:
   905          type: MyExternalStruct
   906          import:
   907            package: github.com/example/models/custom
   908            alias: fred
   909  ```
   910  
   911  Imports will look like so:
   912  ```go
   913  import (
   914    fred "github.com/example/models/custom"
   915  )
   916  ...
   917  ```
   918  
   919  Some deconfliction with other known import is applied automatically. Automatic deconfliction is not perfect, though.
   920  
   921  For example:
   922  ```yaml
   923    MyObject:
   924      type: object
   925      properties:
   926        p1:
   927          x-go-type:
   928            type: RawMessage
   929            import:
   930              package: encoding/json
   931            hints:
   932              kind: interface
   933  ```
   934  
   935  ```go
   936  import (
   937    jsonext "encoding/json"
   938  )
   939  ```
   940  
   941  
   942  ###### Embedding external types
   943  
   944  Sometimes, it is impractical to impose the constraint that the external type has a validation method.
   945  You can then use the "embedded" option to create an embedded type based on the external model, and wraps the Validate
   946  method.
   947  
   948  Example:
   949  ```yaml
   950  definitions:
   951    Time:
   952      type: string
   953      format: date-time         # <- documentary only (external types takes over). This has no impact on generation.
   954      x-go-type:
   955        type: Time
   956        import:
   957          package: time
   958        embedded: true
   959  ```
   960  
   961  This example generates a wrapper type in the package model with a `Validate` method like this:
   962  
   963  ```go
   964  import (
   965  	timeext "time"
   966  
   967  	"github.com/go-openapi/runtime"
   968  	"github.com/go-openapi/strfmt"
   969  	"github.com/go-openapi/swag"
   970  )
   971  
   972  // Time time
   973  //
   974  // swagger:model Time
   975  type Time struct {
   976  	timeext.Time
   977  }
   978  
   979  func (m Time) Validate(formats strfmt.Registry) error {
   980  	var f interface{} = m.Time
   981  	if v, ok := f.(runtime.Validatable); ok {
   982  		return v.Validate(formats)
   983  	}
   984  	return nil
   985  }
   986  ```
   987  
   988  The generated `Validate` method uses any existing `Validate` method or just returns `nil` (i.e. data is valid).
   989  
   990  > **NOTE**: at the moment, we do not support the `format` specification over the embedded type. Format will be documentary only in that case.
   991  
   992  Other examples:
   993  ```yaml
   994    Raw:
   995      x-go-type:
   996        type: RawMessage
   997        import:
   998          package: encoding/json
   999        hints:
  1000          kind: primitive
  1001        embedded: true
  1002  ```
  1003  ```go
  1004  import (
  1005   ...
  1006   jsonext "encoding/json"
  1007   ...
  1008  )
  1009  
  1010  type Raw struct {
  1011  	jsonext.RawMessage
  1012  }
  1013  
  1014  func (m Raw) Validate(formats strfmt.Registry) error {
  1015  	var f interface{} = m.RawMessage
  1016  	if v, ok := f.(runtime.Validatable); ok {
  1017  		return v.Validate(formats)
  1018  	}
  1019  	return nil
  1020  }
  1021  ```
  1022  
  1023  You can embed types as pointers just the same.
  1024  
  1025  Example:
  1026  ```yaml
  1027  definitions:
  1028    Time:
  1029      type: string
  1030      x-go-type:
  1031        type: Time
  1032        import:
  1033          package: time
  1034        hints:
  1035          nullable: true  # <- nullable here refers to the nullability of the embedded external type
  1036        embedded: true
  1037  ```
  1038  
  1039  ```go
  1040  type Time struct {
  1041  	*time.Time
  1042  }
  1043  ```
  1044  
  1045  
  1046  Using external types is powerful, but normally you still have to describe your type in the specification. That is expected,
  1047  since this is how you document your API.
  1048  
  1049  If you don't (that is the type referred to doesn't correspond to the type in the spec), then the generator may fail to produce correct code,
  1050  because it simply has no way to infer what _kind_ of object is being referred to.
  1051  
  1052  To solve this kind of problem, you may hint the generator to produce a correct usage of the external types, even though the specification
  1053  doesn't reflect the correct nature of the object.
  1054  
  1055  Example:
  1056  ```yaml
  1057  definitions:
  1058    Error:
  1059      type: object
  1060  
  1061    Hotspot:
  1062      x-go-type:
  1063        type: Hotspot
  1064        import:
  1065          package: github.com/go-swagger/go-swagger/fixtures/enhancements/2224/external
  1066        hints:
  1067          kind: object
  1068      x-nullable: true
  1069  ```
  1070  In this example, the `Hotspot` schema is empty in the specification. The generator therefore can only guess that this is some `interface{}` type.
  1071  Now thanks to the hint `kind: object`, we instruct the generator to expect an object so as to correctly reference this object.
  1072  
  1073  
  1074  ###### Validation of external types
  1075  
  1076  By default, the generator assumes that external types can be validated and will generate code that calls the "Validate"
  1077  method of the type.
  1078  
  1079  This can be disabled  by providing an explicit hint:
  1080  ```yaml
  1081    MyObject:
  1082      type: object
  1083      properties:
  1084        p1:
  1085          x-go-type:
  1086            type: RawMessage
  1087            import:
  1088              package: encoding/json
  1089            hints:
  1090              noValidation: true
  1091  ```
  1092  
  1093  External types with an hint type "interface" or "stream" do not call validations.
  1094  
  1095  Embedded types use type assertion to dynamically determine if the external type implements the `runtime.Validatable` interface.
  1096  
  1097  
  1098  ###### External type hints
  1099  
  1100  The generator does not attempt to introspect external types. They may even not exist at generation time.
  1101  
  1102  Therefore, the generator has no idea of whether it is safe to generate pointers to the external type.
  1103  
  1104  By default, external types are considered non nullable. This can be altered with the nullable hint or
  1105  by hinting a type that is considered nullable (such as "object").
  1106  
  1107  Supported hints:
  1108  ```yaml
  1109          x-go-type:
  1110            type: {external type name (exported symbol, without package qualifier)}
  1111            import:
  1112              package: {fully qualified package name - defaults to the target models defined by the --model-package flag}
  1113            hints:
  1114              kind: {map|object|array|interface|primitive|tuple|stream}
  1115              noValidation: true|false  # <- skips validation: defaults to true for embedded types, defaults to false for non-embedded, always false for kinds interface and stream
  1116              nullable: true|false      # <- default to true for kinds object,primitive and tuple
  1117            embedded: true|false        # <- defaults to false, generates a struct that wraps the external type
  1118  ```
  1119  
  1120  ###### Caveats with imports
  1121  
  1122  At this moment, external packages and aliases are deconflicted against other known imports and variables.
  1123  
  1124  Example:
  1125  ```yaml
  1126    MyObject:
  1127      type: object
  1128      properties:
  1129        p1:
  1130          x-go-type:
  1131            type: RawMessage
  1132            import:
  1133              package: encoding/json
  1134            hints:
  1135              kind: interface
  1136  ```
  1137  
  1138  will generate an import deconflicted against the standard lib import:
  1139  ```go
  1140  import(
  1141      ...
  1142      jsonext "encoding/json"
  1143      ...
  1144      )
  1145  ```
  1146  
  1147  ###### External package aliasing
  1148  
  1149  External packages may be imported with an alias, like so:
  1150  
  1151  ```yaml
  1152    parameters:
  1153      in: body
  1154      schema:
  1155        type: object
  1156        x-go-type:
  1157          type: MyExternalStruct
  1158          import:
  1159            package: github.com/example/models/custom
  1160            alias: fred
  1161  ```
  1162  
  1163  Imports will look like so:
  1164  ```go
  1165  import (
  1166    fred "github.com/example/models/custom"
  1167  )
  1168  ...
  1169  ```
  1170  
  1171  Some deconfliction with other known imports is applied automatically. Automatic deconfliction is not perfect, though.
  1172  
  1173  For example:
  1174  ```yaml
  1175    MyObject:
  1176      type: object
  1177      properties:
  1178        p1:
  1179          x-go-type:
  1180            type: RawMessage
  1181            import:
  1182              package: encoding/json
  1183            hints:
  1184              kind: interface
  1185  ```
  1186  
  1187  ```go
  1188  import (
  1189    jsonext "encoding/json"
  1190  )
  1191  ```
  1192  
  1193  Package aliases may still conflict with packages produces by operation tags or other external imports.
  1194  
  1195  In such cases, modify the type alias under `x-go-type` to resolve the conflict manually.
  1196  
  1197  ### Customizing struct tags
  1198  
  1199  When a model struct is generated, tags for json are generated to keep the original name:
  1200  
  1201  ```go
  1202  type ObjectWithTag struct {
  1203      StandardTag string `json:"standardTag,omitempty"`
  1204  }
  1205  ```
  1206  
  1207  #### Extra tags
  1208  
  1209  Extra tags may be defined with the CLI generation option `--sruct-tags`.
  1210  
  1211  Extra tags essentially repeat the name of the field can be added from the command line option.
  1212  
  1213  > **NOTE**: at this moment, all tag modifiers (omitempty, string) are repeated like for the json tag.
  1214  
  1215  ```bash
  1216  swagger generate model ... --struct-tags yaml,db
  1217  ```
  1218  
  1219  ```go
  1220  type ObjectWithTag struct {
  1221      StandardTag string `json:"standardTag,omitempty" yaml:"standardTag,omitempty" db:"standardTag,omitempty"`
  1222  }
  1223  ```
  1224  
  1225  #### Custom tags
  1226  
  1227  A custom may be added to a field using the `x-go-custom-tag` extension. Like so:
  1228  
  1229  #### Omit empty values
  1230  
  1231  By default, a struct field is omitted when it holds the zero value (tag modifier: `omitempty`).
  1232  
  1233  Required fields are never omitted.
  1234  
  1235  ```go
  1236  type ObjectWithTag struct {
  1237      RequiredField *string `json:"requiredField"`
  1238  }
  1239  ```
  1240  
  1241  This property can be altered using the `x-omitempty` extension. Like so:
  1242  ```yaml
  1243  objectWithTag:
  1244    type: object
  1245    properties:
  1246      field:
  1247        type: string
  1248        x-omitempty: false
  1249  ```
  1250  
  1251  ```go
  1252  type ObjectWithTag struct {
  1253      Field string `json:"field"`
  1254  }
  1255  ```
  1256  
  1257  The extension does not force a required field to get the "omitempty" modifier.
  1258  
  1259  #### Numerical values as string
  1260  
  1261  For some specific requirements, the standard json library may consider numbers as strings.
  1262  This is done by adding the modifier `json:"...,string"` to the tag.
  1263  
  1264  With go-swagger you can specify this modifier by adding the `x-go-json-string: true` extension to your type.
  1265  
  1266  ```go
  1267  type ObjectWithTag struct {
  1268      NumericField int `json:"field,omitempty,string"`
  1269  }
  1270  ```
  1271  
  1272  #### XML tags
  1273  
  1274  The XML name and attribute Swagger properties are used to generate extra tags.
  1275  ```yaml
  1276  definitions:
  1277   objectWithXML:
  1278     type: object
  1279     properties:
  1280       field:
  1281         type: string
  1282         xml:
  1283           name: xmlObject
  1284           attribute: true
  1285  ```
  1286  
  1287  ```go
  1288  type ObjectWithXML struct {
  1289      Field string `json:"field,omitempty" xml:"xmlObject,attr,omitempty"`
  1290  }
  1291  ```
  1292  
  1293  #### The example tag
  1294  
  1295  If you add `example` to the list of generated tags from the CLI (`swagger generate ... --struct-tags example`),
  1296  a special example tag is created with the example value taken from the specification.
  1297  
  1298  ```yaml
  1299  definitions:
  1300    objectWithExample:
  1301     properties:
  1302       field:
  1303         type: string
  1304         example: "sample"
  1305  ```
  1306  
  1307  ```go
  1308  type ObjectWithExample struct {
  1309      Field string `json:"field,omitempty" example:"\"sample\""`
  1310  }
  1311  ```
  1312  
  1313  #### The description tag
  1314  
  1315  If you add `description` to the list of generated tags from the CLI (`swagger generate ... --struct-tags description`),
  1316  a special description tag is created with the description value taken from the specification.
  1317  
  1318  ```yaml
  1319  definitions:
  1320    objectWithDescription:
  1321     properties:
  1322       field:
  1323         type: string
  1324         description: "some description"
  1325  ```
  1326  
  1327  ```go
  1328  type ObjectWithDescription struct {
  1329      Field string `json:"field,omitempty" description:"\"some description\""`
  1330  }
  1331  ```
  1332  
  1333  
  1334  [swagger]: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#schema-object
  1335  [strfmt]: https://github.com/go-openapi/strfmt
  1336  [runtime]: https://github.com/go-openapi/runtime
  1337  [File]: https://github.com/go-openapi/runtime/blob/master/file.go#L20
  1338  [Validatable]: https://github.com/go-openapi/runtime/blob/master/interfaces.go#L101
  1339  [validate]: https://github.com/go-openapi/validate
  1340  [validate-json]: https://godoc.org/github.com/go-openapi/validate#ex-AgainstSchema
  1341  [go-doc-model]: https://godoc.org/github.com/go-swagger/go-swagger/examples/generated/models
  1342  [read-only]: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#fixed-fields-13
  1343  [all-formats]:  https://github.com/go-openapi/strfmt/blob/master/README.md
  1344  [easy-json]: https://github.com/mailru/easyjson
  1345  [json-schema]: https://tools.ietf.org/html/draft-fge-json-schema-validation-00
  1346  [lifting-pointers]: https://github.com/go-swagger/go-swagger/pull/557