github.com/kaisawind/go-swagger@v0.19.0/docs/faq/faq_model.md (about)

     1  <!-- Questions about model generation -->
     2  
     3  ## Model generation
     4  
     5  ### Custom validation
     6  _Use-Case_: is it possible to write my own validation code for custom types? If so, can someone give me an example?
     7  
     8  >Usage example:
     9  >There is bookstore, with info about books: author, title, price.
    10  > And we want that books from some author will not cost more than some price.
    11  > So I want to write and use a function ValidateBookCustom() like:
    12  ```golang
    13  if book.author == "Some author" {
    14      if book.price > 1000 {
    15         return false
    16     }
    17      else return true
    18  }
    19  ```
    20  
    21  
    22  **Answer**: there are several ways to achieve that.
    23  - reusing customized models
    24  - reusing custom go types
    25  - customizing code generation
    26  
    27  You should know that models may be generated independently from server, then reused when generating a new server.
    28  
    29  You might build on that: generating a first model, customizing the validation code, then reusing this model (possibly with some others) in your servers.
    30  
    31  Another way is to use the `x-go-type extension`, to replace type generation with a custom type.
    32  
    33  There is the opportunity to get go-swagger to reuse a predefined type to satisfy the definition in the swagger spec.
    34  Imported package and type alias may be specified as options, as shown in this example:
    35  https://github.com/go-swagger/go-swagger/blob/master/fixtures/codegen/existing-model.yml#L99-L103
    36  
    37  That example reuses a type provided by a library with a package alias and type name. The code generator will respect this.
    38  
    39  You might use both, preparing a customized model from an initially generated structure, then reusing type custom type in other declarations by hinting the generator with x-go-type.
    40  
    41  Further, for repetitive customization, you might be willing to customize the generator's templates. Like in [here](https://github.com/go-swagger/go-swagger/blob/master/generator/templates/schemavalidator.gotmpl)
    42  for models, or in [here](https://github.com/go-swagger/go-swagger/blob/master/generator/templates/server/parameter.gotmpl) for inline parameters.
    43  
    44  Originally from issues [#997](https://github.com/go-swagger/go-swagger/issues/997) and [#1334](https://github.com/go-swagger/go-swagger/issues/1334)
    45  
    46  ### Non-required or nullable property?
    47  _Use-Case_: when a definition has a property N, if N is a number and is not required,
    48  the corresponding generated model has the struct flag `omitempty` for N.
    49  This means that when N has been set to 0 the generated JSON omits N, despite it being validly set to 0.
    50  
    51  I would still like to allow this variable to be unset, by setting it to null for example.
    52  This will also apply for returning objects that return false and so on.
    53  
    54  >The `"omitempty"` option specifies that the field should be omitted from the encoding if the field has an empty value,
    55  >defined as false, 0, a nil pointer, a nil interface value, and any empty array, slice, map, or string.
    56  >(from https://golang.org/pkg/encoding/json/#Marshal)
    57  
    58  **Hint**: a workaround for this is to use the extension **x-nullable:true** on properties.
    59  
    60  Originally from issue [#959](https://github.com/go-swagger/go-swagger/issues/959). (*more discussion on edge cases there*).
    61  
    62  Related: [go-openapi/validate#19](https://github.com/go-openapi/validate/issues/19).
    63  
    64  ### String parameter in body and query
    65  _Use-case_: I want to create an operation with string parameter in body, but go-swagger fails while generating.
    66  
    67  When I change body to query, it works. How can I send my parameter in body with type string?
    68  
    69  This *works* (param in query):
    70  ```YAML
    71  post:
    72    description: post func
    73    operationId: postfunc
    74    parameters:
    75      - name: myparam
    76        in: query
    77        type: string
    78  ```
    79  **But this fails (param in body):**
    80  ```YAML
    81  post:
    82    description: post func
    83    operationId: postfunc
    84    parameters:
    85      - name: myparam
    86        in: body
    87        type: string
    88  ```
    89  
    90  **Answer**: add the schema definition in body. This works:
    91  ```YAML
    92  post:
    93    description: post func
    94    operationId: postfunc
    95    parameters:
    96      - name: myparam
    97        in: body
    98        required: true
    99        schema:
   100          type: string
   101  ```
   102  
   103  **Hint**: more generally, you might want to check the validity of your spec re the OpenAPI 2.0 schema before trying generation, using the `swagger validate {spec}` command.
   104  
   105  Originally from issue [#990](https://github.com/go-swagger/go-swagger/issues/990).
   106  
   107  ### Request response can have different objects returned based on query parameters
   108  _Use-Case_: I have a POST request that returns different object models based on the query parameters.
   109  
   110  *Is there any way to add multiple responses under the swagger route annotation?*
   111  
   112  Like:
   113  
   114  ```YAML
   115  Responses:
   116    200: response1
   117    200: response2
   118    ... etc
   119  ```
   120  
   121  *Also is it possible to have different models for the request?*
   122  
   123  **Answer**: **No**, as this is not supported in Openapi 2.0 specification
   124  
   125  That being said, if you specify a wrapper class or base class, you can return multiple responses.
   126  
   127  For example (in pseudo-swagger):
   128  
   129  ``` YAML
   130  ResponseWrapper:
   131    type: object
   132    properties:
   133      response1:
   134        $ref: '#/definitions/response1'
   135      response2:
   136        $ref: '#/definitions/response2'
   137  ```
   138  
   139  or perhaps more elegantly:
   140  ``` YAML
   141  BaseObject:
   142    type: object
   143    properties:
   144      id:
   145        type: string
   146        format: uuid
   147  
   148  Response1:
   149    allOf:
   150      - $ref: '#/definitions/BaseObject'
   151      - type: object
   152        properties:
   153          extendedAttributeForResponse1
   154  
   155  Response2:
   156    allOf:
   157      - $ref: '#/definitions/BaseObject'
   158      - type: object
   159         properties:
   160           extendedAttribForResponse2
   161  ```
   162  
   163  Allegedly, with OpenAPI 3.0 you'll be able to use the `anyOf:` operator, with the different response types.
   164  
   165  Regarding parameters, you may also achieve this by putting in the path the query parameters that dictate the model.
   166  ``` YAML
   167  paths:
   168    "/something?objectType=thisThing":
   169        get:
   170  ...
   171    "/something?objectType=otherThing":
   172        get:
   173  ...
   174  ```
   175  
   176  Originally from issue [#932](https://github.com/go-swagger/go-swagger/issues/932).
   177  
   178  ### How to validate dates and times?
   179  JSON schema and Swagger (aka OpenAPI 2.0) define ISO-8601 dates as a known format (e.g. date-time, or `yyyy-MM-dd'T'HH:mm:ss.SSS'Z`).
   180  
   181  This format definition is used by go-swagger validators.
   182  You just have to define the format as in:
   183  ```JSON
   184  {
   185    "description": "The date and time that the device was registered.",
   186    "type":"string",
   187    "format": "date-time"
   188  }
   189  ```
   190  
   191  The `go-openapi/strfmt` package supports many additional string formats for validation.
   192  
   193  Check out for more in [this document](../generate/spec/strfmt.md).
   194  Regarding dates, this package extends validation to [RFC3339](https://tools.ietf.org/html/rfc3339) full-date format (e.g. "2006-01-02").
   195  
   196  Originally from issue [#643](https://github.com/go-swagger/go-swagger/issues/643).
   197  
   198  ### Accessing the Default return value
   199  _Use-Case_: I was wondering how I would get the default response from the client?
   200  
   201  Note: see also [Access HTTP status code from client#597](https://github.com/go-swagger/go-swagger/issues/597).
   202  
   203  I have a spec like this:
   204  ```YAML
   205  /deploys/{deploy_id}:
   206    get:
   207      operationId: getDeploy
   208      parameters:
   209        - name: deploy_id
   210          type: string
   211          in: path
   212          required: true
   213      responses:
   214        '200':
   215          description: OK
   216          schema:
   217            $ref: "#/definitions/deploy"
   218        default:
   219          description: error
   220          schema:
   221            $ref: "#/definitions/error"
   222  ```
   223  This spec generates two models: `GetDeployOK` and `GetDeployDefault`. The API generated will return the OK case.
   224  ```golang
   225  func (a *Client) GetDeploy(params *GetDeployParams, authInfo runtime.ClientAuthInfoWriter) (*GetDeployOK, error) {
   226      // TODO: Validate the params before sending
   227      if params == nil {
   228          params = NewGetDeployParams()
   229      }
   230  
   231      result, err := a.transport.Submit(&runtime.ClientOperation{
   232          ID: "getDeploy",
   233          Method: "GET",
   234          PathPattern: "/deploys/{deploy_id}",
   235          ProducesMediaTypes: []string{"application/json"},
   236          ConsumesMediaTypes: []string{"application/json"},
   237          Schemes: []string{"https"},
   238          Params: params,
   239          Reader: &GetDeployReader{formats: a.formats},
   240          AuthInfo: authInfo,
   241      })
   242      if err != nil {
   243          return nil, err
   244      }
   245      return result.(*GetDeployOK), nil  TODO
   246  }
   247  ```
   248  *Does that mean that, if I get a non-2xx response, I should check the err to actually be a `GetDeployDefault` reference?*
   249  
   250  Something like:
   251  ```golang
   252  resp, err := c.Operations.GetDeploy(&params, authInfo)
   253  if err != nil {
   254      if casted, ok := err.(models.GetDeployDefault); ok {
   255          // do something here....
   256      } else {
   257          false, err
   258      }
   259  }
   260  ```
   261  
   262  >I've been tracing through the code in `Runtime.Submit`: it delegates to the `GetDeployReader.ReadResponse` which makes the distinction.
   263  >However, it remains unclear how that response is actually surfaced.
   264  
   265  **Answer**: you can get pretty close to that with something like:
   266  ```golang
   267  casted, ok := err.(*operations.GetDeployDefault)
   268  ```
   269  
   270  Because it's a struct type it will be a pointer.
   271  
   272  Originally from issue [#616](https://github.com/go-swagger/go-swagger/issues/616).
   273  
   274  ### How to avoid deep copies of complex data structures that need to be marshalled across the API?
   275  _Use-Case_:
   276  >An API that provides access to a complex data structure, defined and governed by a subsystem, should not have to spec the
   277  >same data model to be marshalled, as this would require a deep copy of the data structure from the subsystem to the API layer's
   278  >model universe.
   279  
   280  *How do others deal with this problem?*
   281  
   282  - If your question is "How do I write arbitrary response bodies from go-swagger generated server code?"
   283    (e.g. from subsystem structs that you have marshalled) then you may want to write your own `middleware.Responder`,
   284    which gives you direct access to the underlying `http.ResponseWriter`.
   285    At this point, though, why use go-swagger instead  of a lighter-weight framework?
   286  - If your question is "how can I generate a swagger spec from my subsystem structs?", then you could check out the `swagger generate
   287    spec` CLI command.
   288  
   289  >Further, a subsystem that builds a complex hierarchical data structure to support its own requirements for efficiency,
   290  >access, and serialization does not want the types of the API data model to be injected into its namespace.
   291  
   292  >Eventually, the subsystem can exist in many different contexts beyond the API, which is another reason it should not
   293  >become dependent on any API type.
   294  
   295  -------------
   296  
   297  _Similar Use-Case_:
   298  >A new requirement is proposed that wants API access to that complex data structure, and we decide to use go-swagger for that
   299  >implementation. It is a pure 'read' requirement, so no need for parameter validation by the API, just the ability to gain an XML
   300  >or JSON form of the data structure by a client.
   301  
   302  >Our organization decided to keep the API and subsystem layers separate, and to perform deep copies between them.
   303  >The runtime performance costs are acceptable to us, and worth it to keep API-layer dependencies out of our core library.
   304  >If someone can think of a better solution we would love to know!
   305  
   306  >If we define a data model in the swagger specification, we end up having to do a
   307  >deep copy of that data structure from subsystem to API if we want to avoid type injection.
   308  
   309  *How do you use the swagger spec to define a raw JSON or XML transfer, defined by the subsystem's types?*
   310  
   311  **Hint**: you may use the `x-go-type` model annotation that allows you to use pre-existing types as models, you annotate your spec like this:
   312  https://github.com/go-swagger/go-swagger/blob/master/fixtures/codegen/existing-model.yml#L99-103
   313  
   314  Originally from issue [#948](https://github.com/go-swagger/go-swagger/issues/948).
   315  
   316  ### Extra sections in POST body
   317  
   318  _Use-case_: additional properties in object
   319  
   320  If I have a swagger spec that expects
   321  
   322  {"foo": 123}
   323  
   324  and provide
   325  
   326  {"foo": 123, "blah": 345}
   327  
   328  it happily goes on about this way.
   329  
   330  Two questions:
   331  1. can I make it complain if extra stuff is included
   332  2. can I access these extra sections within the go code/handler?
   333  
   334  **Answer**: use `additionalProperties: false` or `additionalProperties: true` in your definition.
   335  when it's set to true you'll have a `map[string]interface{}` added.
   336  
   337  Originally from issue [#1337](https://github.com/go-swagger/go-swagger/issues/1337).
   338  
   339  ### How to support generate type int?
   340  
   341  _Use-case_: generating `int` types
   342  
   343  > I need to use swagger to generate my modes in go code.
   344  > But I find I can hardly generate type `int`, always `int64`.
   345  > Since I need to keep back compatibility for my project, I can hardly change the type.
   346  > So in this case, does go-swagger meet this requirement?
   347  
   348  **Answer**:  int is not a good option to support when it comes to contracts.
   349  
   350  > Consider the following: you have an arm32 client on which int is int32, however your server is amd64.
   351  > At this stage it's perfectly valid for the server to return int32 max value + 1, this will cause the client to overflow.
   352  > So while go allows int as type I think for API contracts int is too ambiguous as definition leading to subtle but hard to debug failures.
   353  > Similarly other languages may choose to default to int32 type instead of int64 type regardless of platform.
   354  
   355  Originally from issue [#1205](https://github.com/go-swagger/go-swagger/issues/1205).
   356  
   357  ### Generate all models necessary for specified operation
   358  
   359  _Use-case_: I'm specifying specific operations and I'd like to restrict the models to those needed for those operations. Is there a way to do that?
   360  
   361  **Answer:** when using the generate server command, a repeatable --operation=xxx is available to restrict the scope of operations.
   362  
   363   > NOTE: this option is not available for `generate model`.
   364  
   365  Originally from issue [#1427](https://github.com/go-swagger/go-swagger/issues/1427).
   366  
   367  ### Generated code changes the order of properties in struct
   368  
   369  _Use-case_: the generated struct has attributes ordered differently than the original specification
   370  
   371  Example:
   372  
   373  ```yaml
   374  Product:
   375      type: "object"
   376      properties:
   377        product_id:
   378          type: "string"
   379        name:
   380          type: "string"
   381  ```
   382  Generated by "swagger generate server":
   383  ```go
   384  type Product struct {
   385  	Name string `json:"name,omitempty"`
   386  	ProductID string `json:"product_id,omitempty"`
   387  }
   388  ```
   389  I want product_id be the first property of Product struct.
   390  Is there any way to keep the order of properties?
   391  
   392  **Answer:** try x-order: n extension
   393  
   394  Originally from issue [#1759](https://github.com/go-swagger/go-swagger/issues/1759).
   395  
   396  ### Fail to use swagger generate model -name
   397  
   398  _Use-case_: I met a problem when I tried to rename the filename of the auto-generated model.
   399  
   400  Example:
   401  
   402  1. `swagger generate model -m ./models/vo  --name Person`
   403  `unknown models: Person`
   404  2. `swagger generate model -m ./models/vo  -name Person`
   405  `unknown models: ame`
   406  3. `swagger generate model -m ./models/vo  -name= Person`
   407  `unknown models: ame=`
   408  
   409  ```json
   410  {
   411    "swagger": "2.0",
   412     "info": {
   413          "version": "1.0.0",
   414          "title": "Simple API",
   415          "description": "A simple API to learn how to write OpenAPI Specification"
   416      },
   417     "schemes": [
   418          "http"
   419      ],
   420    "paths": {
   421        "/persons":{
   422  	      "get":{
   423  		      "summary":"获取一些目标person",
   424  			  "description": "Returns a list containing all persons.",
   425  			  "responses": {
   426                      "200": {
   427                          "description": "A list of Person",
   428                          "schema": {
   429                              "type": "array",
   430                              "items": {
   431                                  "properties": {
   432                                      "firstName": {
   433                                          "type": "string"
   434                                      },
   435                                      "lastName": {
   436                                          "type": "string"
   437                                      },
   438                                      "username": {
   439                                          "type": "string"
   440                                      }
   441                                  }
   442                              }
   443                          }
   444                      }
   445                  }
   446  		  }
   447  	}
   448    }
   449  }
   450  ```
   451  
   452  **Answer:** you need to make it available with that name in the definitions section then it will know
   453  
   454  Originally from issue [#1517](https://github.com/go-swagger/go-swagger/issues/1517).
   455  
   456  -------------
   457  
   458  Back to [all contributions](README.md#all-contributed-questions)