wI2L / fizz

:lemon: Gin wrapper with OpenAPI 3 spec generation
https://pkg.go.dev/github.com/wI2L/fizz
MIT License
214 stars 52 forks source link

feat(openapi/explode): explicitly set false in specs #112

Open tbourrelovh opened 4 months ago

tbourrelovh commented 4 months ago

Why

Using omitempty with bool type ends up having the configuration not being set in openapi spec file.

As default value for the explode configuration is true (see this page), when we want to set it to false, it is not defined in the spec file.

Example reproducer based on this repository master branch:

package main

import (
        "io/ioutil"
        "log"
        "net/http/httptest"
        "time"

        "github.com/gin-gonic/gin"
        "github.com/loopfz/gadgeto/tonic"
        "github.com/wI2L/fizz"
        "github.com/wI2L/fizz/openapi"
)

type inputModel struct {
        MyQueryParam []string `query:"myQueryParam" explode:"false"`
}

func main() {
        f := fizz.New()

        f.GET("/test", []fizz.OperationOption{
                fizz.InputModel(&inputModel{}),
        }, tonic.Handler(func(c *gin.Context) error {
                return nil
        }, 200))

        infos := &openapi.Info{
                Title:       "Test Server",
                Description: `This is a test server.`,
                Version:     "1.0.0",
        }
        f.GET("/openapi.json", nil, f.OpenAPI(infos, "")) // default is JSON
        srv := httptest.NewServer(f)
        defer srv.Close()

        c := srv.Client()
        c.Timeout = 1 * time.Second

        respJSON, _ := c.Get(srv.URL + "/openapi.json")
        defer respJSON.Body.Close()

        specJSON, _ := ioutil.ReadAll(respJSON.Body)
        log.Println(string(specJSON))
}

json spec output:

{
  "openapi": "3.0.1",
  "info": {
    "title": "Test Server",
    "description": "This is a test server.",
    "version": "1.0.0"
  },
  "paths": {
    "/test": {
      "get": {
        "operationId": "func1",
        "parameters": [
          {
            "name": "myQueryParam",
            "in": "query",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            "style": "form"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    }
  },
  "components": {}
}

As you can see, explode is missing in the myQueryParam parameter configuration, making it impossible to override it's default value which is true.

When I set explode:"true" in inputModel struct, spec file looks like this:

{
  "openapi": "3.0.1",
  "info": {
    "title": "Test Server",
    "description": "This is a test server.",
    "version": "1.0.0"
  },
  "paths": {
    "/test": {
      "get": {
        "operationId": "func1",
        "parameters": [
          {
            "name": "myQueryParam",
            "in": "query",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            "style": "form",
            "explode": true
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    }
  },
  "components": {}
}

With true, swagger will generate the following query parameter string: ?myQueryParam=a&myQueryParam=b, while when set it false, it generates ?myQueryParam=a,b. Where a and b are fake values for myQueryParam.