-
Notifications
You must be signed in to change notification settings - Fork 329
Description
Issue found in version 1.5.7
I want to use the functionality provided by json-schema-validator to apply defaults as part of the validation process, so I have changed the logic in my app to use the walk
method instead of validate
. However, I am now facing validation errors that were never raised as part of the validate
call. The error is related to how we automatically generate nullable types in the app, which means definitions end up like this:
"REASON" : {
"oneOf" : [ {
"type" : "string"
}, {
"type" : "null"
} ]
}
I am aware that the type of the property could be defined like: "type" = ["string", "null"]
and this makes the walk
method behave the same as validate
. But unfortunately, it is not possible to apply this approach when the two types are object
and null
, so you must use oneOf
and the walk
method still raises validation errors. Please see sample unit test in Kotlin below to reproduce the problem using the object
and null
approach (easily swappable for oneOf
string
and null
as well):
@Test
fun `test validate vs walk-validate`() {
val simpleSchema = """
{
"properties" : {
"USER_NAME" : {
"description" : "User name",
"type" : "string",
"default" : "JohnDoe"
},
"VALIDATE" : {
"type" : "boolean"
},
"REASON" : {
"oneOf" : [ {
"type" : "object",
"properties" : {
"TEXT" : {
"type" : "string"
}
}
}, {
"type" : "null"
} ]
}
},
"required" : [ "VALIDATE" ],
"additionalProperties" : true,
"description" : "Test",
"title": "Test",
"${'$'}defs" : { },
"type" : "object"
}
""".trimIndent()
val simplePayload = """
{
"VALIDATE": true
}
""".trimIndent()
val config = SchemaValidatorsConfig.builder()
.applyDefaultsStrategy(
ApplyDefaultsStrategy(true, true, true)
)
.build()
val schemaFactory = JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V201909)
val schema = schemaFactory.getSchema(simpleSchema, config)
val objectMapper = ObjectMapper()
val jsonNode = objectMapper.readTree(simplePayload) as ObjectNode
assertTrue(!jsonNode.has("USER_NAME"))
val validationResult = schema.validate(jsonNode)
assertTrue(validationResult.isEmpty()) // Works as expected
val walkValidation = schema.walk(jsonNode, true)
assertTrue(jsonNode.has("USER_NAME")) // jsonNode now contains USER_NAME as expected
assertEquals(1, walkValidation.validationMessages.size) // but there is one validation error...
assertEquals(
"/REASON: must be valid to one and only one schema, but 2 are valid with indexes '0, 1'",
walkValidation.validationMessages.first().toString()
)
}