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(¶ms, 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)