@@ -17,6 +17,7 @@ package schema
17
17
18
18
import (
19
19
"encoding/json"
20
+ "fmt"
20
21
"regexp"
21
22
22
23
"github.com/arduino/go-paths-helper"
@@ -76,10 +77,10 @@ func validationErrorMatch(
76
77
logrus .Tracef ("Checking instance pointer: %s match with regexp: %s" , validationError .InstancePtr , instancePointerRegexp )
77
78
if instancePointerRegexp .MatchString (validationError .InstancePtr ) {
78
79
logrus .Tracef ("Matched!" )
79
- logrus . Tracef ( "Checking schema pointer: %s match with regexp: %s" , validationError . SchemaPtr , schemaPointerRegexp )
80
- if schemaPointerRegexp . MatchString ( validationError . SchemaPtr ) {
80
+ matchedSchemaPointer := validationErrorSchemaPointerMatch ( schemaPointerRegexp , validationError , schemasPath )
81
+ if matchedSchemaPointer != "" {
81
82
logrus .Tracef ("Matched!" )
82
- if validationErrorSchemaPointerValueMatch (schemaPointerValueRegexp , validationError , schemasPath ) {
83
+ if validationErrorSchemaPointerValueMatch (schemaPointerValueRegexp , validationError . SchemaURL , matchedSchemaPointer , schemasPath ) {
83
84
logrus .Tracef ("Matched!" )
84
85
logrus .Tracef ("Checking failure context: %v match with regexp: %s" , validationError .Context , failureContextRegexp )
85
86
if validationErrorContextMatch (failureContextRegexp , validationError ) {
@@ -107,14 +108,67 @@ func validationErrorMatch(
107
108
return false
108
109
}
109
110
111
+ // validationErrorSchemaPointerMatch matches the JSON schema pointer related to the validation failure against a regular expression.
112
+ func validationErrorSchemaPointerMatch (
113
+ schemaPointerRegexp * regexp.Regexp ,
114
+ validationError * jsonschema.ValidationError ,
115
+ schemasPath * paths.Path ,
116
+ ) string {
117
+ logrus .Tracef ("Checking schema pointer: %s match with regexp: %s" , validationError .SchemaPtr , schemaPointerRegexp )
118
+ if schemaPointerRegexp .MatchString (validationError .SchemaPtr ) {
119
+ return validationError .SchemaPtr
120
+ }
121
+
122
+ // The schema validator does not provide full pointer past logic inversion keywords to the lowest level keywords related to the validation error cause.
123
+ // Therefore the sub-keywords must be checked for matches in order to be able to interpret the exact cause of the failure.
124
+ if regexp .MustCompile ("(/not)|(/oneOf)$" ).MatchString (validationError .SchemaPtr ) {
125
+ return validationErrorSchemaSubPointerMatch (schemaPointerRegexp , validationError .SchemaPtr , validationErrorSchemaPointerValue (validationError , schemasPath ))
126
+ }
127
+
128
+ return ""
129
+ }
130
+
131
+ // validationErrorSchemaSubPointerMatch recursively checks JSON pointers of all keywords under the parent pointer for match against a regular expression.
132
+ // The matching JSON pointer is returned.
133
+ func validationErrorSchemaSubPointerMatch (schemaPointerRegexp * regexp.Regexp , parentPointer string , pointerValueObject interface {}) string {
134
+ // Recurse through iterable objects.
135
+ switch assertedObject := pointerValueObject .(type ) {
136
+ case []interface {}:
137
+ for index , element := range assertedObject {
138
+ // Append index to JSON pointer and check for match.
139
+ matchingPointer := validationErrorSchemaSubPointerMatch (schemaPointerRegexp , fmt .Sprintf ("%s/%d" , parentPointer , index ), element )
140
+ if matchingPointer != "" {
141
+ return matchingPointer
142
+ }
143
+ }
144
+ case map [string ]interface {}:
145
+ for key := range assertedObject {
146
+ // Append key to JSON pointer and check for match.
147
+ matchingPointer := validationErrorSchemaSubPointerMatch (schemaPointerRegexp , parentPointer + "/" + key , assertedObject [key ])
148
+ if matchingPointer != "" {
149
+ return matchingPointer
150
+ }
151
+ // TODO: Follow references. For now, the schema code must be written so that the problematic keywords are after the reference.
152
+ }
153
+ }
154
+
155
+ // pointerValueObject is not further iterable. Check for match against the parent JSON pointer.
156
+ logrus .Tracef ("Checking schema pointer: %s match with regexp: %s" , parentPointer , schemaPointerRegexp )
157
+ if schemaPointerRegexp .MatchString (parentPointer ) {
158
+ return parentPointer
159
+ }
160
+ return ""
161
+ }
162
+
110
163
// validationErrorSchemaPointerValueMatch marshalls the data in the schema at the given JSON pointer and returns whether
111
164
// it matches against the given regular expression.
112
165
func validationErrorSchemaPointerValueMatch (
113
166
schemaPointerValueRegexp * regexp.Regexp ,
114
- validationError * jsonschema.ValidationError ,
167
+ schemaURL ,
168
+ schemaPointer string ,
115
169
schemasPath * paths.Path ,
116
170
) bool {
117
- marshalledSchemaPointerValue , err := json .Marshal (schemaPointerValue (validationError , schemasPath ))
171
+ marshalledSchemaPointerValue , err := json .Marshal (schemaPointerValue (schemaURL , schemaPointer , schemasPath ))
118
172
logrus .Tracef ("Checking schema pointer value: %s match with regexp: %s" , marshalledSchemaPointerValue , schemaPointerValueRegexp )
119
173
if err != nil {
120
174
panic (err )
0 commit comments