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

     1  ---
     2  title: About generating models
     3  date: 2023-01-01T01:01:01-08:00
     4  draft: true
     5  ---
     6  <!-- Questions about model generation -->
     7  
     8  ## Model generation
     9  
    10  ### Custom validation
    11  _Use-Case_: is it possible to write my own validation code for custom types? If so, can someone give me an example?
    12  
    13  >Usage example:
    14  >There is bookstore, with info about books: author, title, price.
    15  > And we want that books from some author will not cost more than some price.
    16  > So I want to write and use a function ValidateBookCustom() like:
    17  ```golang
    18  if book.author == "Some author" {
    19      if book.price > 1000 {
    20         return false
    21     }
    22      else return true
    23  }
    24  ```
    25  
    26  
    27  **Answer**: there are several ways to achieve that.
    28  - reusing customized models
    29  - reusing custom go types
    30  - customizing code generation
    31  
    32  You should know that models may be generated independently from server, then reused when generating a new server.
    33  
    34  You might build on that: generating a first model, customizing the validation code, then reusing this model (possibly with some others) in your servers.
    35  
    36  Another way is to use the `x-go-type extension`, to replace type generation with a custom type.
    37  
    38  There is the opportunity to get go-swagger to reuse a predefined type to satisfy the definition in the swagger spec.
    39  Imported package and type alias may be specified as options, as shown in this example:
    40  https://github.com/go-swagger/go-swagger/blob/master/fixtures/codegen/existing-model.yml#L99-L103
    41  
    42  That example reuses a type provided by a library with a package alias and type name. The code generator will respect this.
    43  
    44  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.
    45  
    46  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)
    47  for models, or in [here](https://github.com/go-swagger/go-swagger/blob/master/generator/templates/server/parameter.gotmpl) for inline parameters.
    48  
    49  Originally from issues [#997](https://github.com/go-swagger/go-swagger/issues/997) and [#1334](https://github.com/go-swagger/go-swagger/issues/1334)
    50  
    51  ### Non-required or nullable property?
    52  _Use-Case_: when a definition has a property N, if N is a number and is not required,
    53  the corresponding generated model has the struct flag `omitempty` for N.
    54  This means that when N has been set to 0 the generated JSON omits N, despite it being validly set to 0.
    55  
    56  I would still like to allow this variable to be unset, by setting it to null for example.
    57  This will also apply for returning objects that return false and so on.
    58  
    59  >The `"omitempty"` option specifies that the field should be omitted from the encoding if the field has an empty value,
    60  >defined as false, 0, a nil pointer, a nil interface value, and any empty array, slice, map, or string.
    61  >(from https://golang.org/pkg/encoding/json/#Marshal)
    62  
    63  **Hint**: a workaround for this is to use the extension **x-nullable:true** on properties.
    64  
    65  Originally from issue [#959](https://github.com/go-swagger/go-swagger/issues/959). (*more discussion on edge cases there*).
    66  
    67  Related: [go-openapi/validate#19](https://github.com/go-openapi/validate/issues/19).
    68  
    69  ### String parameter in body and query
    70  _Use-case_: I want to create an operation with string parameter in body, but go-swagger fails while generating.
    71  
    72  When I change body to query, it works. How can I send my parameter in body with type string?
    73  
    74  This *works* (param in query):
    75  ```YAML
    76  post:
    77    description: post func
    78    operationId: postfunc
    79    parameters:
    80      - name: myparam
    81        in: query
    82        type: string
    83  ```
    84  **But this fails (param in body):**
    85  ```YAML
    86  post:
    87    description: post func
    88    operationId: postfunc
    89    parameters:
    90      - name: myparam
    91        in: body
    92        type: string
    93  ```
    94  
    95  **Answer**: add the schema definition in body. This works:
    96  ```YAML
    97  post:
    98    description: post func
    99    operationId: postfunc
   100    parameters:
   101      - name: myparam
   102        in: body
   103        required: true
   104        schema:
   105          type: string
   106  ```
   107  
   108  **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.
   109  
   110  Originally from issue [#990](https://github.com/go-swagger/go-swagger/issues/990).
   111  
   112  ### Request response can have different objects returned based on query parameters
   113  _Use-Case_: I have a POST request that returns different object models based on the query parameters.
   114  
   115  *Is there any way to add multiple responses under the swagger route annotation?*
   116  
   117  Like:
   118  
   119  ```YAML
   120  Responses:
   121    200: response1
   122    200: response2
   123    ... etc
   124  ```
   125  
   126  *Also is it possible to have different models for the request?*
   127  
   128  **Answer**: **No**, as this is not supported in Openapi 2.0 specification
   129  
   130  That being said, if you specify a wrapper class or base class, you can return multiple responses.
   131  
   132  For example (in pseudo-swagger):
   133  
   134  ``` YAML
   135  ResponseWrapper:
   136    type: object
   137    properties:
   138      response1:
   139        $ref: '#/definitions/response1'
   140      response2:
   141        $ref: '#/definitions/response2'
   142  ```
   143  
   144  or perhaps more elegantly:
   145  ``` YAML
   146  BaseObject:
   147    type: object
   148    properties:
   149      id:
   150        type: string
   151        format: uuid
   152  
   153  Response1:
   154    allOf:
   155      - $ref: '#/definitions/BaseObject'
   156      - type: object
   157        properties:
   158          extendedAttributeForResponse1
   159  
   160  Response2:
   161    allOf:
   162      - $ref: '#/definitions/BaseObject'
   163      - type: object
   164         properties:
   165           extendedAttribForResponse2
   166  ```
   167  
   168  Allegedly, with OpenAPI 3.0 you'll be able to use the `anyOf:` operator, with the different response types.
   169  
   170  Regarding parameters, you may also achieve this by putting in the path the query parameters that dictate the model.
   171  ``` YAML
   172  paths:
   173    "/something?objectType=thisThing":
   174        get:
   175  ...
   176    "/something?objectType=otherThing":
   177        get:
   178  ...
   179  ```
   180  
   181  Originally from issue [#932](https://github.com/go-swagger/go-swagger/issues/932).
   182  
   183  ### How to validate dates and times?
   184  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`).
   185  
   186  This format definition is used by go-swagger validators.
   187  You just have to define the format as in:
   188  ```JSON
   189  {
   190    "description": "The date and time that the device was registered.",
   191    "type":"string",
   192    "format": "date-time"
   193  }
   194  ```
   195  
   196  The `go-openapi/strfmt` package supports many additional string formats for validation.
   197  
   198  Check out for more in [this repo](https://github.com/go-openapi/strfmt/tree/master/README.md). The full API
   199  is documented [here](https://godoc.org/github.com/go-openapi/strfmt).
   200  
   201  Regarding dates, this package extends validation to [RFC3339](https://tools.ietf.org/html/rfc3339) full-date format (e.g. "2006-01-02").
   202  
   203  Originally from issue [#643](https://github.com/go-swagger/go-swagger/issues/643).
   204  
   205  ### Accessing the Default return value
   206  _Use-Case_: I was wondering how I would get the default response from the client?
   207  
   208  Note: see also [Access HTTP status code from client#597](https://github.com/go-swagger/go-swagger/issues/597).
   209  
   210  I have a spec like this:
   211  ```YAML
   212  /deploys/{deploy_id}:
   213    get:
   214      operationId: getDeploy
   215      parameters:
   216        - name: deploy_id
   217          type: string
   218          in: path
   219          required: true
   220      responses:
   221        '200':
   222          description: OK
   223          schema:
   224            $ref: "#/definitions/deploy"
   225        default:
   226          description: error
   227          schema:
   228            $ref: "#/definitions/error"
   229  ```
   230  This spec generates two models: `GetDeployOK` and `GetDeployDefault`. The API generated will return the OK case.
   231  ```golang
   232  func (a *Client) GetDeploy(params *GetDeployParams, authInfo runtime.ClientAuthInfoWriter) (*GetDeployOK, error) {
   233      // TODO: Validate the params before sending
   234      if params == nil {
   235          params = NewGetDeployParams()
   236      }
   237  
   238      result, err := a.transport.Submit(&runtime.ClientOperation{
   239          ID: "getDeploy",
   240          Method: "GET",
   241          PathPattern: "/deploys/{deploy_id}",
   242          ProducesMediaTypes: []string{"application/json"},
   243          ConsumesMediaTypes: []string{"application/json"},
   244          Schemes: []string{"https"},
   245          Params: params,
   246          Reader: &GetDeployReader{formats: a.formats},
   247          AuthInfo: authInfo,
   248      })
   249      if err != nil {
   250          return nil, err
   251      }
   252      return result.(*GetDeployOK), nil  TODO
   253  }
   254  ```
   255  *Does that mean that, if I get a non-2xx response, I should check the err to actually be a `GetDeployDefault` reference?*
   256  
   257  Something like:
   258  ```golang
   259  resp, err := c.Operations.GetDeploy(&params, authInfo)
   260  if err != nil {
   261      if casted, ok := err.(models.GetDeployDefault); ok {
   262          // do something here....
   263      } else {
   264          false, err
   265      }
   266  }
   267  ```
   268  
   269  >I've been tracing through the code in `Runtime.Submit`: it delegates to the `GetDeployReader.ReadResponse` which makes the distinction.
   270  >However, it remains unclear how that response is actually surfaced.
   271  
   272  **Answer**: you can get pretty close to that with something like:
   273  ```golang
   274  casted, ok := err.(*operations.GetDeployDefault)
   275  ```
   276  
   277  Because it's a struct type it will be a pointer.
   278  
   279  Originally from issue [#616](https://github.com/go-swagger/go-swagger/issues/616).
   280  
   281  ### How to avoid deep copies of complex data structures that need to be marshalled across the API?
   282  _Use-Case_:
   283  >An API that provides access to a complex data structure, defined and governed by a subsystem, should not have to spec the
   284  >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
   285  >model universe.
   286  
   287  *How do others deal with this problem?*
   288  
   289  - If your question is "How do I write arbitrary response bodies from go-swagger generated server code?"
   290    (e.g. from subsystem structs that you have marshalled) then you may want to write your own `middleware.Responder`,
   291    which gives you direct access to the underlying `http.ResponseWriter`.
   292    At this point, though, why use go-swagger instead  of a lighter-weight framework?
   293  - If your question is "how can I generate a swagger spec from my subsystem structs?", then you could check out the `swagger generate
   294    spec` CLI command.
   295  
   296  >Further, a subsystem that builds a complex hierarchical data structure to support its own requirements for efficiency,
   297  >access, and serialization does not want the types of the API data model to be injected into its namespace.
   298  
   299  >Eventually, the subsystem can exist in many different contexts beyond the API, which is another reason it should not
   300  >become dependent on any API type.
   301  
   302  
   303  Back to [all contributions](/faq)