Skip to content

Commit

Permalink
generator: handle Style/Explode values for Query parameters.
Browse files Browse the repository at this point in the history
  • Loading branch information
wI2L committed Feb 11, 2019
1 parent 6b46127 commit 330bf5b
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 10 deletions.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,10 +182,11 @@ type MyHandlerParams struct {
You can use additional tags. Some will be interpreted by *tonic*, others will be exclusively used to enrich the *OpenAPI* specification.
- `default`: *tonic* will bind this value if none was passed with the request. This should not be used if a field is also required. Read the [documentation](https://swagger.io/docs/specification/describing-parameters/) (section _Common Mistakes_) for more informations about this behaviour.
- `description`: Add a description of the field in the spec.
- `deprecated`: Indicates if the field is deprecated. accepted values are _1_, _t_, _T_, _TRUE_, _true_, _True_, _0_, _f_, _F_, _FALSE_. Invalid value are considered to be false.
- `deprecated`: Indicates if the field is deprecated. Accepted values are _1_, _t_, _T_, _TRUE_, _true_, _True_, _0_, _f_, _F_, _FALSE_. Invalid value are considered to be false.
- `enum`: A coma separated list of acceptable values for the parameter.
- `format`: Override the format of the field in the specification. Read the [documentation](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#dataTypeFormat) for more informations.
- `validate`: Field validation rules. Read the [documentation](https://godoc.org/gopkg.in/go-playground/validator.v8) for more informations.
- `explode`: Specifies whether arrays should generate separate parameters for each array item or object property (limited to query parameters with *form* style). Accepted values are _1_, _t_, _T_, _TRUE_, _true_, _True_, _0_, _f_, _F_, _FALSE_. Invalid value are considered to be false.

### JSON/XML

Expand Down Expand Up @@ -244,7 +245,8 @@ The names of the components can be customized in two different ways.

Override the name of a type globally before registering your handlers. This has the highest precedence.
```go
fizz.Generator().OverrideTypeName(reflect.TypeOf(T{}), "OverridedName")
f := fizz.New()
f.Generator().OverrideTypeName(reflect.TypeOf(T{}), "OverridedName")
```

##### Interface
Expand Down
26 changes: 19 additions & 7 deletions openapi/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ const (
descriptionTag = "description"
)

var (
paramsInPathRe = regexp.MustCompile(`\{(.*?)\}`)
ginPathParamRe = regexp.MustCompile(`\/:([^\/]*)`)
)

// mediaTags maps media types to well-known
// struct tags used for marshaling.
var mediaTags = map[string]string{
Expand Down Expand Up @@ -281,8 +286,6 @@ func (g *Generator) AddOperation(path, method, tag string, in, out reflect.Type,
return nil
}

var ginPathParamRe = regexp.MustCompile(`\/:([^\/]*)`)

// rewritePath converts a Gin operation path that use
// colons and asterisks to declare path parameters, to
// an OpenAPI representation that use curly braces.
Expand Down Expand Up @@ -386,8 +389,6 @@ func (g *Generator) setOperationResponse(op *Operation, t reflect.Type, code, mt
return nil
}

var paramsInPathRe = regexp.MustCompile(`\{(.*?)\}`)

// setOperationParams adds the fields of the struct type t
// to the given operation.
func (g *Generator) setOperationParams(op *Operation, t, parent reflect.Type, allowBody bool, path string) error {
Expand Down Expand Up @@ -603,7 +604,7 @@ func (g *Generator) newParameterFromField(idx int, t reflect.Type) (*Parameter,
}
required := g.isStructFieldRequired(field)

// Path parameters are aways required.
// Path parameters are always required.
if location == g.config.PathLocationTag {
required = true
}
Expand All @@ -621,6 +622,18 @@ func (g *Generator) newParameterFromField(idx int, t reflect.Type) (*Parameter,
if field.Type.Kind() == reflect.Bool && location == g.config.QueryLocationTag {
p.AllowEmptyValue = true
}
// Style.
if location == g.config.QueryLocationTag {
if field.Type.Kind() == reflect.Slice || field.Type.Kind() == reflect.Array {
p.Explode = true // default
p.Style = "form" // default in spec, but make it obvious
if t := field.Tag.Get(tonic.ExplodeTag); t != "" {
if explode, err := strconv.ParseBool(t); err == nil && !explode { // ignore invalid values
p.Explode = explode
}
}
}
}
return p, nil
}

Expand Down Expand Up @@ -820,8 +833,7 @@ func (g *Generator) buildSchemaRecursive(t reflect.Type) *SchemaOrRef {
// in additional properties field.
schema.Type = "object"

// JSON Schema allow only strings as
// object key.
// JSON Schema allow only strings as object key.
if t.Key().Kind() != reflect.String {
g.error(&TypeError{
Message: "encountered type Map with keys of unsupported type",
Expand Down
2 changes: 2 additions & 0 deletions openapi/spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ type Parameter struct {
Deprecated bool `json:"deprecated,omitempty" yaml:"deprecated,omitempty"`
AllowEmptyValue bool `json:"allowEmptyValue,omitempty" yaml:"allowEmptyValue,omitempty"`
Schema *SchemaOrRef `json:"schema,omitempty" yaml:"schema,omitempty"`
Style string `json:"style,omitempty" yaml:"style,omitempty"`
Explode bool `json:"explode,omitempty" yaml:"explode,omitempty"`
}

// ParameterOrRef represents a Parameter that can be inlined
Expand Down
4 changes: 3 additions & 1 deletion testdata/schemas/path-item.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,9 @@
"ccc"
]
}
}
},
"explode": true,
"style": "form"
},
{
"name": "xd",
Expand Down

0 comments on commit 330bf5b

Please sign in to comment.