github.com/josephspurrier/go-swagger@v0.2.1-0.20221129144919-1f672a142a00/docs/use/models/schemas.md (about)

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