@@ -5,16 +5,52 @@ package parameters
55
66import (
77 "encoding/json"
8+ stdError "errors"
89 "fmt"
10+ "net/url"
11+ "reflect"
12+ "strings"
13+
914 "github.com/pb33f/libopenapi-validator/errors"
1015 "github.com/pb33f/libopenapi/datamodel/high/base"
1116 "github.com/pb33f/libopenapi/utils"
1217 "github.com/santhosh-tekuri/jsonschema/v5"
13- "net/url"
14- "reflect"
15- "strings"
1618)
1719
20+ func ValidateSingleParameterSchema (
21+ schema * base.Schema ,
22+ rawObject any ,
23+ entity string ,
24+ reasonEntity string ,
25+ name string ,
26+ validationType string ,
27+ subValType string ,
28+ ) (validationErrors []* errors.ValidationError ) {
29+ jsch := compileSchema (name , buildJsonRender (schema ))
30+
31+ scErrs := jsch .Validate (rawObject )
32+ var werras * jsonschema.ValidationError
33+ if stdError .As (scErrs , & werras ) {
34+ validationErrors = formatJsonSchemaValidationError (schema , werras , entity , reasonEntity , name , validationType , subValType )
35+ }
36+ return validationErrors
37+ }
38+
39+ // compileSchema create a new json schema compiler and add the schema to it.
40+ func compileSchema (name string , jsonSchema []byte ) * jsonschema.Schema {
41+ compiler := jsonschema .NewCompiler ()
42+ _ = compiler .AddResource (fmt .Sprintf ("%s.json" , name ), strings .NewReader (string (jsonSchema )))
43+ jsch , _ := compiler .Compile (fmt .Sprintf ("%s.json" , name ))
44+ return jsch
45+ }
46+
47+ // buildJsonRender build a JSON render of the schema.
48+ func buildJsonRender (schema * base.Schema ) []byte {
49+ renderedSchema , _ := schema .Render ()
50+ jsonSchema , _ := utils .ConvertYAMLtoJSON (renderedSchema )
51+ return jsonSchema
52+ }
53+
1854// ValidateParameterSchema will validate a parameter against a raw object, or a blob of json/yaml.
1955// It will return a list of validation errors, if any.
2056//
@@ -108,35 +144,9 @@ func ValidateParameterSchema(
108144 }
109145 }
110146 }
111- if scErrs != nil {
112- jk := scErrs .(* jsonschema.ValidationError )
113-
114- // flatten the validationErrors
115- schFlatErrs := jk .BasicOutput ().Errors
116- var schemaValidationErrors []* errors.SchemaValidationFailure
117- for q := range schFlatErrs {
118- er := schFlatErrs [q ]
119- if er .KeywordLocation == "" || strings .HasPrefix (er .Error , "doesn't validate with" ) {
120- continue // ignore this error, it's not useful
121- }
122- schemaValidationErrors = append (schemaValidationErrors , & errors.SchemaValidationFailure {
123- Reason : er .Error ,
124- Location : er .KeywordLocation ,
125- OriginalError : jk ,
126- })
127- }
128- // add the error to the list
129- validationErrors = append (validationErrors , & errors.ValidationError {
130- ValidationType : validationType ,
131- ValidationSubType : subValType ,
132- Message : fmt .Sprintf ("%s '%s' failed to validate" , entity , name ),
133- Reason : fmt .Sprintf ("%s '%s' is defined as an object, " +
134- "however it failed to pass a schema validation" , reasonEntity , name ),
135- SpecLine : schema .GoLow ().Type .KeyNode .Line ,
136- SpecCol : schema .GoLow ().Type .KeyNode .Column ,
137- SchemaValidationErrors : schemaValidationErrors ,
138- HowToFix : errors .HowToFixInvalidSchema ,
139- })
147+ var werras * jsonschema.ValidationError
148+ if stdError .As (scErrs , & werras ) {
149+ validationErrors = formatJsonSchemaValidationError (schema , werras , entity , reasonEntity , name , validationType , subValType )
140150 }
141151
142152 // if there are no validationErrors, check that the supplied value is even JSON
@@ -159,3 +169,36 @@ func ValidateParameterSchema(
159169 }
160170 return validationErrors
161171}
172+
173+ func formatJsonSchemaValidationError (schema * base.Schema , scErrs * jsonschema.ValidationError , entity string , reasonEntity string , name string , validationType string , subValType string ) (validationErrors []* errors.ValidationError ) {
174+ // flatten the validationErrors
175+ schFlatErrs := scErrs .BasicOutput ().Errors
176+ var schemaValidationErrors []* errors.SchemaValidationFailure
177+ for q := range schFlatErrs {
178+ er := schFlatErrs [q ]
179+ if er .KeywordLocation == "" || strings .HasPrefix (er .Error , "doesn't validate with" ) {
180+ continue // ignore this error, it's not useful
181+ }
182+ schemaValidationErrors = append (schemaValidationErrors , & errors.SchemaValidationFailure {
183+ Reason : er .Error ,
184+ Location : er .KeywordLocation ,
185+ OriginalError : scErrs ,
186+ })
187+ }
188+ schemaType := "undefined"
189+ if len (schema .Type ) > 0 {
190+ schemaType = schema .Type [0 ]
191+ }
192+ validationErrors = append (validationErrors , & errors.ValidationError {
193+ ValidationType : validationType ,
194+ ValidationSubType : subValType ,
195+ Message : fmt .Sprintf ("%s '%s' failed to validate" , entity , name ),
196+ Reason : fmt .Sprintf ("%s '%s' is defined as an %s, " +
197+ "however it failed to pass a schema validation" , reasonEntity , name , schemaType ),
198+ SpecLine : schema .GoLow ().Type .KeyNode .Line ,
199+ SpecCol : schema .GoLow ().Type .KeyNode .Column ,
200+ SchemaValidationErrors : schemaValidationErrors ,
201+ HowToFix : errors .HowToFixInvalidSchema ,
202+ })
203+ return validationErrors
204+ }
0 commit comments