Model generation

Non-required or nullable property?

Use-Case: when a definition has a property N, if N is a number and is not required, the corresponding generated model has the struct flag omitempty for N. This means that when N has been set to 0 the generated JSON omits N, despite it being validly set to 0.

I would still like to allow this variable to be unset, by setting it to null for example. This will also apply for returning objects that return false and so on.

The "omitempty" option specifies that the field should be omitted from the encoding if the field has an empty value, defined as false, 0, a nil pointer, a nil interface value, and any empty array, slice, map, or string. (from https://golang.org/pkg/encoding/json/#Marshal)

Hint: a workaround for this is to use the extension x-nullable:true on properties.

Originally from issue #959. (more discussion on edge cases there).

Related: go-openapi/validate#19.

String parameter in body and query

Use-case: I want to create an operation with string parameter in body, but go-swagger fails while generating.

When I change body to query, it works. How can I send my parameter in body with type string?

This works (param in query):

post:
  description: post func
  operationId: postfunc
  parameters:
    - name: myparam
      in: query
      type: string

But this fails (param in body):

post:
  description: post func
  operationId: postfunc
  parameters:
    - name: myparam
      in: body
      type: string

Answer: add the schema definition in body. This works:

post:
  description: post func
  operationId: postfunc
  parameters:
    - name: myparam
      in: body
      required: true
      schema:
        type: string

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.

Originally from issue #990.

Request response can have different objects returned based on query parameters

Use-Case: I have a POST request that returns different object models based on the query parameters.

Is there any way to add multiple responses under the swagger route annotation?

Like:

Responses:
  200: response1
  200: response2
  ... etc

Also is it possible to have different models for the request?

Answer: No, as this is not supported in Openapi 2.0 specification

That being said, if you specify a wrapper class or base class, you can return multiple responses.

For example (in pseudo-swagger):

ResponseWrapper:
  type: object
  properties:
    response1:
      $ref: '#/definitions/response1'
    response2:
      $ref: '#/definitions/response2'

or perhaps more elegantly:

BaseObject:
  type: object
  properties:
    id:
      type: string
      format: uuid

Response1:
  allOf:
    - $ref: '#/definitions/BaseObject'
    - type: object
      properties:
        extendedAttributeForResponse1

Response2:
  allOf:
    - $ref: '#/definitions/BaseObject'
    - type: object
       properties:
         extendedAttribForResponse2

Allegedly, with OpenAPI 3.0 you'll be able to use the anyOf: operator, with the different response types.

Regarding parameters, you may also achieve this by putting in the path the query parameters that dictate the model.

paths:
  "/something?objectType=thisThing":
      get:
...
  "/something?objectType=otherThing":
      get:
...

Originally from issue #932.

How to validate dates and times?

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).

This format definition is used by go-swagger validators. You just have to define the format as in:

{
  "description": "The date and time that the device was registered.",
  "type":"string",
  "format": "date-time"
}

The go-openapi/strfmt package supports many additional string formats for validation.

Check out for more in this document. Regarding dates, this package extends validation to RFC3339 full-date format (e.g. "2006-01-02").

Originally from issue #643.

Accessing the Default return value

Use-Case: I was wondering how I would get the default response from the client?

Note: see also Access HTTP status code from client#597.

I have a spec like this:

/deploys/{deploy_id}:
  get:
    operationId: getDeploy
    parameters:
      - name: deploy_id
        type: string
        in: path
        required: true
    responses:
      '200':
        description: OK
        schema:
          $ref: "#/definitions/deploy"
      default:
        description: error
        schema:
          $ref: "#/definitions/error"

This spec generates two models: GetDeployOK and GetDeployDefault. The API generated will return the OK case.

func (a *Client) GetDeploy(params *GetDeployParams, authInfo runtime.ClientAuthInfoWriter) (*GetDeployOK, error) {
    // TODO: Validate the params before sending
    if params == nil {
        params = NewGetDeployParams()
    }

    result, err := a.transport.Submit(&runtime.ClientOperation{
        ID: "getDeploy",
        Method: "GET",
        PathPattern: "/deploys/{deploy_id}",
        ProducesMediaTypes: []string{"application/json"},
        ConsumesMediaTypes: []string{"application/json"},
        Schemes: []string{"https"},
        Params: params,
        Reader: &GetDeployReader{formats: a.formats},
        AuthInfo: authInfo,
    })
    if err != nil {
        return nil, err
    }
    return result.(*GetDeployOK), nil  TODO
}

Does that mean that, if I get a non-2xx response, I should check the err to actually be a GetDeployDefault reference?

Something like:

resp, err := c.Operations.GetDeploy(&params, authInfo)
if err != nil {
    if casted, ok := err.(models.GetDeployDefault); ok {
        // do something here....
    } else {
        false, err
    }
}

I've been tracing through the code in Runtime.Submit: it delegates to the GetDeployReader.ReadResponse which makes the distinction. However, it remains unclear how that response is actually surfaced.

Answer: you can get pretty close to that with something like:

casted, ok := err.(*operations.GetDeployDefault)

Because it's a struct type it will be a pointer.

Originally from issue #616.

How to avoid deep copies of complex data structures that need to be marshalled across the API?

Use-Case:

An API that provides access to a complex data structure, defined and governed by a subsystem, should not have to spec the 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 model universe.

How do others deal with this problem?

  • If your question is "How do I write arbitrary response bodies from go-swagger generated server code?" (e.g. from subsystem structs that you have marshalled) then you may want to write your own middleware.Responder, which gives you direct access to the underlying http.ResponseWriter. At this point, though, why use go-swagger instead of a lighter-weight framework?
  • If your question is "how can I generate a swagger spec from my subsystem structs?", then you could check out the swagger generate spec CLI command.

Further, a subsystem that builds a complex hierarchical data structure to support its own requirements for efficiency, access, and serialization does not want the types of the API data model to be injected into its namespace.

Eventually, the subsystem can exist in many different contexts beyond the API, which is another reason it should not become dependent on any API type.


Similar Use-Case:

A new requirement is proposed that wants API access to that complex data structure, and we decide to use go-swagger for that implementation. It is a pure 'read' requirement, so no need for parameter validation by the API, just the ability to gain an XML or JSON form of the data structure by a client.

Our organization decided to keep the API and subsystem layers separate, and to perform deep copies between them. The runtime performance costs are acceptable to us, and worth it to keep API-layer dependencies out of our core library. If someone can think of a better solution we would love to know!

If we define a data model in the swagger specification, we end up having to do a deep copy of that data structure from subsystem to API if we want to avoid type injection.

How do you use the swagger spec to define a raw JSON or XML transfer, defined by the subsystem's types?

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: https://github.com/go-swagger/go-swagger/blob/master/fixtures/codegen/existing-model.yml#L84-L88

Originally from issue #948.


Back to all contributions

results matching ""

    No results matching ""