diff --git a/README.md b/README.md index 8bb80d825..efbb3380a 100644 --- a/README.md +++ b/README.md @@ -478,6 +478,7 @@ Field Name | Type | Description default | * | Declares the value of the parameter that the server will use if none is provided, for example a "count" to control the number of results per page might default to 100 if not supplied by the client in the request. (Note: "default" has no meaning for required parameters.) See https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-6.2. Unlike JSON Schema this value MUST conform to the defined [`type`](#parameterType) for this parameter. maximum | `number` | See https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-5.1.2. minimum | `number` | See https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-5.1.3. +multipleOf | `number` | See https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-5.1.1. maxLength | `integer` | See https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-5.2.1. minLength | `integer` | See https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-5.2.2. enums | [\*] | See https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-5.5.1. @@ -488,7 +489,6 @@ Field Name | Type | Description Field Name | Type | Description ---|:---:|--- -multipleOf | `number` | See https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-5.1.1. pattern | `string` | See https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-5.2.3. maxItems | `integer` | See https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-5.3.2. minItems | `integer` | See https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-5.3.3. diff --git a/parser.go b/parser.go index aaa8112a5..1149eeb69 100644 --- a/parser.go +++ b/parser.go @@ -986,6 +986,7 @@ type structField struct { exampleValue interface{} maximum *float64 minimum *float64 + multipleOf *float64 maxLength *int64 minLength *int64 enums []interface{} @@ -1077,6 +1078,7 @@ func (parser *Parser) parseStructField(file *ast.File, field *ast.Field) (map[st } eleSchema.Maximum = structField.maximum eleSchema.Minimum = structField.minimum + eleSchema.MultipleOf = structField.multipleOf eleSchema.MaxLength = structField.maxLength eleSchema.MinLength = structField.minLength eleSchema.Enum = structField.enums @@ -1269,6 +1271,12 @@ func (parser *Parser) parseFieldTag(field *ast.Field, types []string) (*structFi return nil, err } structField.minimum = minimum + + multipleOf, err := getFloatTag(structTag, "multipleOf") + if err != nil { + return nil, err + } + structField.multipleOf = multipleOf } if structField.schemaType == STRING || structField.arrayType == STRING { maxLength, err := getIntTag(structTag, "maxLength") diff --git a/parser_test.go b/parser_test.go index 4cdc5faf4..a0012883f 100644 --- a/parser_test.go +++ b/parser_test.go @@ -980,6 +980,7 @@ func TestParseSimpleApi_ForSnakecase(t *testing.T) { }, "price": { "type": "number", + "multipleOf": 0.01, "example": 3.25 }, "status": { @@ -1435,6 +1436,7 @@ func TestParseSimpleApi_ForLowerCamelcase(t *testing.T) { }, "price": { "type": "number", + "multipleOf": 0.01, "example": 3.25 }, "status": { @@ -3259,6 +3261,29 @@ func TestParseFieldTag(t *testing.T) { []string{"number"}) assert.Error(t, err) + field, err = parser.parseFieldTag( + &ast.Field{ + Tag: &ast.BasicLit{ + Value: `json:"test" multipleOf:"1"`, + }, + }, + []string{"number"}) + assert.NoError(t, err) + multipleOf := float64(1) + assert.Equal(t, &structField{ + schemaType: "number", + multipleOf: &multipleOf, + }, field) + + _, err = parser.parseFieldTag( + &ast.Field{ + Tag: &ast.BasicLit{ + Value: `json:"test" multipleOf:"one"`, + }, + }, + []string{"number"}) + assert.Error(t, err) + field, err = parser.parseFieldTag( &ast.Field{ Tag: &ast.BasicLit{ diff --git a/testdata/pet/web/handler.go b/testdata/pet/web/handler.go index 759999d41..f2994d51a 100644 --- a/testdata/pet/web/handler.go +++ b/testdata/pet/web/handler.go @@ -16,7 +16,7 @@ type Pet struct { PhotoUrls []string `json:"photo_urls" example:"http://test/image/1.jpg,http://test/image/2.jpg"` Tags []Tag `json:"tags"` Status string `json:"status"` - Price float32 `json:"price" example:"3.25"` + Price float32 `json:"price" example:"3.25" multipleOf:"0.01"` IsAlive bool `json:"is_alive" example:"true"` } diff --git a/testdata/simple/expected.json b/testdata/simple/expected.json index c8967ae14..eb224b956 100644 --- a/testdata/simple/expected.json +++ b/testdata/simple/expected.json @@ -556,6 +556,7 @@ "type": "number", "maximum": 1000, "minimum": 1, + "multipleOf": 0.01, "example": 3.25 }, "status": { diff --git a/testdata/simple/web/handler.go b/testdata/simple/web/handler.go index 0e3c2ae74..8f42b07a7 100644 --- a/testdata/simple/web/handler.go +++ b/testdata/simple/web/handler.go @@ -26,7 +26,7 @@ type Pet struct { Pets *[]Pet2 `json:"pets"` Pets2 []*Pet2 `json:"pets2"` Status string `json:"status" enums:"healthy,ill"` - Price float32 `json:"price" example:"3.25" minimum:"1.0" maximum:"1000"` + Price float32 `json:"price" example:"3.25" minimum:"1.0" maximum:"1000" multipleOf:"0.01"` IsAlive bool `json:"is_alive" example:"true" default:"true"` Data interface{} `json:"data"` Hidden string `json:"-"` diff --git a/testdata/simple2/web/handler.go b/testdata/simple2/web/handler.go index bf5923d6c..0cff04af2 100644 --- a/testdata/simple2/web/handler.go +++ b/testdata/simple2/web/handler.go @@ -47,7 +47,7 @@ type Pet struct { Pets *[]Pet2 Pets2 []*Pet2 Status string - Price float32 `example:"3.25" validate:"required,gte=0,lte=130"` + Price float32 `example:"3.25" validate:"required,gte=0,lte=130" multipleOf:"0.01"` IsAlive bool `example:"true"` Data interface{} Hidden string `json:"-"` diff --git a/testdata/simple3/web/handler.go b/testdata/simple3/web/handler.go index 505b7620b..61da78c50 100644 --- a/testdata/simple3/web/handler.go +++ b/testdata/simple3/web/handler.go @@ -25,7 +25,7 @@ type Pet struct { Pets *[]Pet2 Pets2 []*Pet2 Status string - Price float32 `example:"3.25"` + Price float32 `example:"3.25" multipleOf:"0.01"` IsAlive bool `example:"true"` Data interface{} Hidden string `json:"-"`