@@ -17,6 +17,7 @@ package jsonschema
17
17
18
18
import (
19
19
"encoding/json"
20
+ "fmt"
20
21
"reflect"
21
22
"strings"
22
23
@@ -55,14 +56,22 @@ func New(data []byte) (*JSONSchema, error) {
55
56
// ProcessObject checks if the object is valid from this schema's standpoint
56
57
// and returns an object with defaults set up according to schema's spec
57
58
func (j * JSONSchema ) ProcessObject (in interface {}) (interface {}, error ) {
58
- result , err := j .schema .Validate (gojsonschema .NewGoLoader (in ))
59
+ defaults := setDefaults (j .rawSchema , in )
60
+
61
+ result , err := j .schema .Validate (gojsonschema .NewGoLoader (defaults ))
59
62
if err != nil {
60
63
return nil , trace .Wrap (err )
61
64
}
62
65
if ! result .Valid () {
63
- return nil , trace .Wrap (trace .Errorf ("errors: %v" , schemaErrors (result .Errors ())))
66
+ errors := result .Errors ()
67
+ output := make ([]string , len (errors ))
68
+ for i , err := range errors {
69
+ output [i ] = fmt .Sprintf ("%v" , err )
70
+ }
71
+
72
+ return nil , trace .Errorf ("failed to validate: %v" , strings .Join (output , "," ))
64
73
}
65
- return setDefaults ( j . rawSchema , in ) , nil
74
+ return defaults , nil
66
75
}
67
76
68
77
func setDefaults (ischema interface {}, ivars interface {}) interface {} {
@@ -73,37 +82,49 @@ func setDefaults(ischema interface{}, ivars interface{}) interface{} {
73
82
if ! ok {
74
83
return ivars
75
84
}
76
- tp := getStringProp (schema , "type" )
77
- switch tp {
85
+ itemType := getStringProp (schema , "type" )
86
+ switch itemType {
78
87
case "object" :
79
- vars , ok := ivars .(map [string ]interface {})
80
- if ! ok {
81
- return ivars
82
- }
83
- if len (vars ) == 0 {
84
- vars = make (map [string ]interface {})
88
+ var vars map [string ]interface {}
89
+ if ivars == nil {
90
+ vars = map [string ]interface {}{}
91
+ } else {
92
+ var ok bool
93
+ vars , ok = ivars .(map [string ]interface {})
94
+ if ! ok {
95
+ return ivars
96
+ }
85
97
}
86
- props , ok := getProperties ( schema , "properties" )
87
- if ! ok {
98
+ var props map [ string ] interface {}
99
+ if props = getSchemaProperties ( schema , vars ); props == nil {
88
100
return ivars
89
101
}
90
102
out := make (map [string ]interface {})
91
103
for key , prop := range props {
92
104
_ , have := vars [key ]
93
105
defval := setDefaults (prop , vars [key ])
94
106
// only set default value if the property
95
- // is missing and retunred default value is not empty
107
+ // is missing and returned default value is not empty
96
108
// otherwise we will return a bunch of nils
97
109
if ! have && isEmpty (defval ) {
98
110
continue
99
111
}
100
112
out [key ] = defval
101
113
}
114
+ if len (out ) == 0 {
115
+ return nil
116
+ }
102
117
return out
103
118
case "array" :
104
- vars , ok := ivars .([]interface {})
105
- if ! ok {
106
- return ivars
119
+ var vars []interface {}
120
+ if ivars == nil {
121
+ vars = []interface {}{}
122
+ } else {
123
+ var ok bool
124
+ vars , ok = ivars .([]interface {})
125
+ if ! ok {
126
+ return ivars
127
+ }
107
128
}
108
129
if len (vars ) == 0 {
109
130
return ivars
@@ -130,6 +151,27 @@ func setDefaults(ischema interface{}, ivars interface{}) interface{} {
130
151
return ivars
131
152
}
132
153
154
+ func getSchemaProperties (schema map [string ]interface {}, input map [string ]interface {}) map [string ]interface {} {
155
+ objectProperties , ok := getProperties (schema , "properties" )
156
+ if ! ok {
157
+ if objectProperties , ok = getProperties (schema , "patternProperties" ); ! ok {
158
+ return nil
159
+ }
160
+ // pattern properties define a single property with a name pattern;
161
+ // we ignore the pattern - validation will verify if it's correct
162
+ var property interface {}
163
+ for _ , property = range objectProperties {
164
+ }
165
+ // override the result to contain the pattern property for each
166
+ // input key
167
+ objectProperties = map [string ]interface {}{}
168
+ for key , _ := range input {
169
+ objectProperties [key ] = property
170
+ }
171
+ }
172
+ return objectProperties
173
+ }
174
+
133
175
func isEmpty (x interface {}) bool {
134
176
return x == nil || reflect .DeepEqual (x , reflect .Zero (reflect .TypeOf (x )).Interface ())
135
177
}
@@ -161,11 +203,3 @@ func getProperties(schema map[string]interface{}, name string) (map[string]inter
161
203
}
162
204
return v , true
163
205
}
164
-
165
- func schemaErrors (errors []gojsonschema.ResultError ) string {
166
- out := make ([]string , len (errors ))
167
- for i , err := range errors {
168
- out [i ] = err .Description ()
169
- }
170
- return strings .Join (out , "," )
171
- }
0 commit comments