Skip to content

Commit

Permalink
Rewrite "additionalProperties" validation logic and fix the context w…
Browse files Browse the repository at this point in the history
…hen a schema inside "additionalProperties" produces an error
  • Loading branch information
johandorland committed Aug 16, 2019
1 parent 9486476 commit d5a76c7
Showing 1 changed file with 30 additions and 97 deletions.
127 changes: 30 additions & 97 deletions validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -601,100 +601,37 @@ func (v *subSchema) validateObject(currentSubSchema *subSchema, value map[string
}

// additionalProperty & patternProperty:
if currentSubSchema.additionalProperties != nil {

switch currentSubSchema.additionalProperties.(type) {
case bool:

if !currentSubSchema.additionalProperties.(bool) {

for pk := range value {

found := false
for _, spValue := range currentSubSchema.propertiesChildren {
if pk == spValue.property {
found = true
}
}

ppHas, ppMatch := v.validatePatternProperty(currentSubSchema, pk, value[pk], result, context)

if found {

if ppHas && !ppMatch {
result.addInternalError(
new(AdditionalPropertyNotAllowedError),
context,
value[pk],
ErrorDetails{"property": pk},
)
}

} else {

if !ppHas || !ppMatch {
result.addInternalError(
new(AdditionalPropertyNotAllowedError),
context,
value[pk],
ErrorDetails{"property": pk},
)
}

}
}
}

case *subSchema:

additionalPropertiesSchema := currentSubSchema.additionalProperties.(*subSchema)
for pk := range value {

found := false
for _, spValue := range currentSubSchema.propertiesChildren {
if pk == spValue.property {
found = true
}
}

ppHas, ppMatch := v.validatePatternProperty(currentSubSchema, pk, value[pk], result, context)

if found {

if ppHas && !ppMatch {
validationResult := additionalPropertiesSchema.subValidateWithContext(value[pk], context)
result.mergeErrors(validationResult)
}

} else {

if !ppHas || !ppMatch {
validationResult := additionalPropertiesSchema.subValidateWithContext(value[pk], context)
result.mergeErrors(validationResult)
}

}
for pk := range value {

// Check whether this property is described by "properties"
found := false
for _, spValue := range currentSubSchema.propertiesChildren {
if pk == spValue.property {
found = true
}
}
} else {

for pk := range value {

ppHas, ppMatch := v.validatePatternProperty(currentSubSchema, pk, value[pk], result, context)
// Check whether this property is described by "patternProperties"
ppMatch := v.validatePatternProperty(currentSubSchema, pk, value[pk], result, context)

if ppHas && !ppMatch {
// If it is not described by neither "properties" nor "patternProperties" it must pass "additionalProperties"
if !found && !ppMatch {
switch ap := currentSubSchema.additionalProperties.(type) {
case bool:
// Handle the boolean case separately as it's cleaner to return a specific error than failing to pass the false schema
if !ap {
result.addInternalError(
new(AdditionalPropertyNotAllowedError),
context,
value[pk],
ErrorDetails{"property": pk},
)

result.addInternalError(
new(InvalidPropertyPatternError),
context,
value[pk],
ErrorDetails{
"property": pk,
},
)
}
case *subSchema:
validationResult := ap.subValidateWithContext(value[pk], NewJsonContext(pk, context))
result.mergeErrors(validationResult)
}

}
}

Expand All @@ -716,34 +653,30 @@ func (v *subSchema) validateObject(currentSubSchema *subSchema, value map[string
result.incrementScore()
}

func (v *subSchema) validatePatternProperty(currentSubSchema *subSchema, key string, value interface{}, result *Result, context *JsonContext) (has bool, matched bool) {
func (v *subSchema) validatePatternProperty(currentSubSchema *subSchema, key string, value interface{}, result *Result, context *JsonContext) bool {

if internalLogEnabled {
internalLog("validatePatternProperty %s", context.String())
internalLog(" %s %v", key, value)
}

has = false

validatedkey := false
validated := false

for pk, pv := range currentSubSchema.patternProperties {
if matches, _ := regexp.MatchString(pk, key); matches {
has = true
validated = true
subContext := NewJsonContext(key, context)
validationResult := pv.subValidateWithContext(value, subContext)
result.mergeErrors(validationResult)
validatedkey = true
}
}

if !validatedkey {
return has, false
if !validated {
return false
}

result.incrementScore()

return has, true
return true
}

func (v *subSchema) validateString(currentSubSchema *subSchema, value interface{}, result *Result, context *JsonContext) {
Expand Down

0 comments on commit d5a76c7

Please sign in to comment.