Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions fixtures/allow_additional_props.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
},
"name": {
"type": "string",
"const": "alex",
"maxLength": 20,
"minLength": 1,
"pattern": ".*",
Expand Down Expand Up @@ -80,10 +81,12 @@
},
"TestFlagFalse": {
"type": "boolean",
"const": false,
"default": false
},
"TestFlagTrue": {
"type": "boolean",
"const": true,
"default": true
},
"birth_date": {
Expand Down
4 changes: 4 additions & 0 deletions fixtures/array_handling.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
"minLength": 2
},
"type": "array",
"const": [
"foo",
"bar"
],
"default": [
"qwerty"
]
Expand Down
3 changes: 3 additions & 0 deletions fixtures/defaults_expanded_toplevel.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
},
"name": {
"type": "string",
"const": "alex",
"maxLength": 20,
"minLength": 1,
"pattern": ".*",
Expand Down Expand Up @@ -80,10 +81,12 @@
},
"TestFlagFalse": {
"type": "boolean",
"const": false,
"default": false
},
"TestFlagTrue": {
"type": "boolean",
"const": true,
"default": true
},
"birth_date": {
Expand Down
3 changes: 3 additions & 0 deletions fixtures/ignore_type.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
},
"name": {
"type": "string",
"const": "alex",
"maxLength": 20,
"minLength": 1,
"pattern": ".*",
Expand Down Expand Up @@ -74,10 +75,12 @@
},
"TestFlagFalse": {
"type": "boolean",
"const": false,
"default": false
},
"TestFlagTrue": {
"type": "boolean",
"const": true,
"default": true
},
"birth_date": {
Expand Down
3 changes: 3 additions & 0 deletions fixtures/no_reference.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
},
"name": {
"type": "string",
"const": "alex",
"maxLength": 20,
"minLength": 1,
"pattern": ".*",
Expand Down Expand Up @@ -68,10 +69,12 @@
},
"TestFlagFalse": {
"type": "boolean",
"const": false,
"default": false
},
"TestFlagTrue": {
"type": "boolean",
"const": true,
"default": true
},
"birth_date": {
Expand Down
3 changes: 3 additions & 0 deletions fixtures/no_reference_anchor.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
},
"name": {
"type": "string",
"const": "alex",
"maxLength": 20,
"minLength": 1,
"pattern": ".*",
Expand Down Expand Up @@ -70,10 +71,12 @@
},
"TestFlagFalse": {
"type": "boolean",
"const": false,
"default": false
},
"TestFlagTrue": {
"type": "boolean",
"const": true,
"default": true
},
"birth_date": {
Expand Down
2 changes: 2 additions & 0 deletions fixtures/number_handling.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@
"properties": {
"int64": {
"type": "integer",
"const": 12,
"default": 12
},
"float32": {
"type": "number",
"const": 12.5,
"default": 12.5
}
},
Expand Down
3 changes: 3 additions & 0 deletions fixtures/required_from_jsontags.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
},
"name": {
"type": "string",
"const": "alex",
"maxLength": 20,
"minLength": 1,
"pattern": ".*",
Expand Down Expand Up @@ -81,10 +82,12 @@
},
"TestFlagFalse": {
"type": "boolean",
"const": false,
"default": false
},
"TestFlagTrue": {
"type": "boolean",
"const": true,
"default": true
},
"birth_date": {
Expand Down
3 changes: 3 additions & 0 deletions fixtures/test_user.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
},
"name": {
"type": "string",
"const": "alex",
"maxLength": 20,
"minLength": 1,
"pattern": ".*",
Expand Down Expand Up @@ -81,10 +82,12 @@
},
"TestFlagFalse": {
"type": "boolean",
"const": false,
"default": false
},
"TestFlagTrue": {
"type": "boolean",
"const": true,
"default": true
},
"birth_date": {
Expand Down
3 changes: 3 additions & 0 deletions fixtures/test_user_assign_anchor.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
},
"name": {
"type": "string",
"const": "alex",
"maxLength": 20,
"minLength": 1,
"pattern": ".*",
Expand Down Expand Up @@ -83,10 +84,12 @@
},
"TestFlagFalse": {
"type": "boolean",
"const": false,
"default": false
},
"TestFlagTrue": {
"type": "boolean",
"const": true,
"default": true
},
"birth_date": {
Expand Down
27 changes: 21 additions & 6 deletions reflect.go
Original file line number Diff line number Diff line change
Expand Up @@ -744,12 +744,15 @@ func (t *Schema) booleanKeywords(tags []string) {
continue
}
name, val := nameValue[0], nameValue[1]
if name == "default" {
if val == "true" {
t.Default = true
} else if val == "false" {
t.Default = false
}
b, err := strconv.ParseBool(val)
if err != nil {
continue
}
switch name {
case "default":
t.Default = b
case "const":
t.Const = b
}
}
}
Expand Down Expand Up @@ -780,6 +783,8 @@ func (t *Schema) stringKeywords(tags []string) {
t.WriteOnly = i
case "default":
t.Default = val
case "const":
t.Const = val
case "example":
t.Examples = append(t.Examples, val)
case "enum":
Expand Down Expand Up @@ -810,6 +815,10 @@ func (t *Schema) numericalKeywords(tags []string) {
if num, ok := toJSONNumber(val); ok {
t.Default = num
}
case "const":
if num, ok := toJSONNumber(val); ok {
t.Const = num
}
case "example":
if num, ok := toJSONNumber(val); ok {
t.Examples = append(t.Examples, num)
Expand Down Expand Up @@ -842,6 +851,7 @@ func (t *Schema) numericalKeywords(tags []string) {
// read struct tags for array type keywords
func (t *Schema) arrayKeywords(tags []string) {
var defaultValues []any
var constValues []any

unprocessed := make([]string, 0, len(tags))
for _, tag := range tags {
Expand All @@ -857,6 +867,8 @@ func (t *Schema) arrayKeywords(tags []string) {
t.UniqueItems = true
case "default":
defaultValues = append(defaultValues, val)
case "const":
constValues = append(constValues, val)
case "format":
t.Items.Format = val
case "pattern":
Expand All @@ -869,6 +881,9 @@ func (t *Schema) arrayKeywords(tags []string) {
if len(defaultValues) > 0 {
t.Default = defaultValues
}
if len(constValues) > 0 {
t.Const = constValues
}

if len(unprocessed) == 0 {
// we don't have anything else to process
Expand Down
16 changes: 9 additions & 7 deletions reflect_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,16 +64,16 @@ type TestUser struct {
nonExported
MapType

ID int `json:"id" jsonschema:"required,minimum=bad,maximum=bad,exclusiveMinimum=bad,exclusiveMaximum=bad,default=bad"`
Name string `json:"name" jsonschema:"required,minLength=1,maxLength=20,pattern=.*,description=this is a property,title=the name,example=joe,example=lucy,default=alex,readOnly=true"`
ID int `json:"id" jsonschema:"required,minimum=bad,maximum=bad,exclusiveMinimum=bad,exclusiveMaximum=bad,default=bad,const=bad"`
Name string `json:"name" jsonschema:"required,minLength=1,maxLength=20,pattern=.*,description=this is a property,title=the name,example=joe,example=lucy,default=alex,const=alex,readOnly=true"`
Password string `json:"password" jsonschema:"writeOnly=true"`
Friends []int `json:"friends,omitempty" jsonschema_description:"list of IDs, omitted when empty"`
Tags map[string]string `json:"tags,omitempty"`
Options map[string]any `json:"options,omitempty"`

TestFlag bool
TestFlagFalse bool `json:",omitempty" jsonschema:"default=false"`
TestFlagTrue bool `json:",omitempty" jsonschema:"default=true"`
TestFlagFalse bool `json:",omitempty" jsonschema:"default=false,const=false"`
TestFlagTrue bool `json:",omitempty" jsonschema:"default=true,const=true"`
IgnoredCounter int `json:"-"`

// Tests for RFC draft-wright-json-schema-validation-00, section 7.3
Expand Down Expand Up @@ -585,19 +585,21 @@ func TestFieldOneOfRef(t *testing.T) {

func TestNumberHandling(t *testing.T) {
type NumberHandler struct {
Int64 int64 `json:"int64" jsonschema:"default=12"`
Float32 float32 `json:"float32" jsonschema:"default=12.5"`
Int64 int64 `json:"int64" jsonschema:"default=12,const=12"`
Float32 float32 `json:"float32" jsonschema:"default=12.5,const=12.5"`
}

r := &Reflector{}
compareSchemaOutput(t, "fixtures/number_handling.json", r, &NumberHandler{})
fixtureContains(t, "fixtures/number_handling.json", `"default": 12`)
fixtureContains(t, "fixtures/number_handling.json", `"default": 12.5`)
fixtureContains(t, "fixtures/number_handling.json", `"const": 12`)
fixtureContains(t, "fixtures/number_handling.json", `"const": 12.5`)
}

func TestArrayHandling(t *testing.T) {
type ArrayHandler struct {
MinLen []string `json:"min_len" jsonschema:"minLength=2,default=qwerty"`
MinLen []string `json:"min_len" jsonschema:"minLength=2,default=qwerty,const=foo,const=bar"`
MinVal []float64 `json:"min_val" jsonschema:"minimum=2.5"`
}

Expand Down