Skip to content

Commit 8bd68f0

Browse files
committed
feat(jsonschema): Field to tell if RootSchema is an array or object.
1 parent 1280440 commit 8bd68f0

File tree

3 files changed

+57
-4
lines changed

3 files changed

+57
-4
lines changed

keywords.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,14 @@ func NewType() Validator {
5959
return &Type{}
6060
}
6161

62+
// FirstValue returns the first element in the values of this type.
63+
func (t Type) FirstValue() string {
64+
if len(t.vals) == 0 {
65+
return ""
66+
}
67+
return t.vals[0]
68+
}
69+
6270
// Validate checks to see if input data satisfies the type constraint
6371
func (t Type) Validate(propPath string, data interface{}, errs *[]ValError) {
6472
jt := DataType(data)

schema.go

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,15 @@ type RootSchema struct {
4646
// for current and previous published drafts of JSON Schema
4747
// vocabularies as deemed reasonable.
4848
SchemaURI string `json:"$schema"`
49+
// Whether the top-level of the schema is an array or not.
50+
// Assume it's an object otherwise.
51+
TopIsArray bool
52+
}
53+
54+
func determineTopIsArray(sch *Schema) bool {
55+
validator := sch.Validators["type"]
56+
typeValidator, ok := validator.(*Type)
57+
return ok && typeValidator.FirstValue() == "array"
4958
}
5059

5160
// UnmarshalJSON implements the json.Unmarshaler interface for
@@ -55,6 +64,7 @@ func (rs *RootSchema) UnmarshalJSON(data []byte) error {
5564
if err := json.Unmarshal(data, sch); err != nil {
5665
return err
5766
}
67+
topIsArray := determineTopIsArray(sch)
5868

5969
if sch.schemaType == schemaTypeFalse || sch.schemaType == schemaTypeTrue {
6070
*rs = RootSchema{Schema: *sch}
@@ -69,8 +79,9 @@ func (rs *RootSchema) UnmarshalJSON(data []byte) error {
6979
}
7080

7181
root := &RootSchema{
72-
Schema: *sch,
73-
SchemaURI: suri.SchemaURI,
82+
Schema: *sch,
83+
SchemaURI: suri.SchemaURI,
84+
TopIsArray: topIsArray,
7485
}
7586

7687
// collect IDs for internal referencing:
@@ -122,8 +133,9 @@ func (rs *RootSchema) UnmarshalJSON(data []byte) error {
122133
}
123134

124135
*rs = RootSchema{
125-
Schema: *sch,
126-
SchemaURI: suri.SchemaURI,
136+
Schema: *sch,
137+
SchemaURI: suri.SchemaURI,
138+
TopIsArray: topIsArray,
127139
}
128140
return nil
129141
}

schema_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,39 @@ func ExampleBasic() {
7979
// /friends/0: {"firstName":"Nas"} "lastName" value is required
8080
}
8181

82+
func TestTopLevelType(t *testing.T) {
83+
schemaObject := []byte(`{
84+
"title": "Car",
85+
"type": "object",
86+
"properties": {
87+
"color": {
88+
"type": "string"
89+
}
90+
},
91+
"required": ["color"]
92+
}`)
93+
rs := &RootSchema{}
94+
if err := json.Unmarshal(schemaObject, rs); err != nil {
95+
panic("unmarshal schema: " + err.Error())
96+
}
97+
if rs.TopIsArray {
98+
t.Errorf("error: schemaObject should not be an array")
99+
}
100+
101+
schemaArray := []byte(`{
102+
"title": "Cities",
103+
"type": "array",
104+
"items" : { "title" : "REFERENCE", "$ref" : "#" }
105+
}`)
106+
rs = &RootSchema{}
107+
if err := json.Unmarshal(schemaArray, rs); err != nil {
108+
panic("unmarshal schema: " + err.Error())
109+
}
110+
if !rs.TopIsArray {
111+
t.Errorf("error: schemaArray should not be an object")
112+
}
113+
}
114+
82115
func TestMust(t *testing.T) {
83116
defer func() {
84117
if r := recover(); r != nil {

0 commit comments

Comments
 (0)