Skip to content

walk(jsonNode, true) raises validation error, but validate(jsonNode) doesn't #1177

@jacinpoz

Description

@jacinpoz

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()
        )
    }

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions