7

I'm using a JSON schema template to validate the data that is received by an online form. One of the requirements of the validator is that it allows some questions to be required based on the answers given for other questions.

For example if the question is Do you want a loan? and the user answers yes, then the answer to the question What is the loan to be used for? needs to be set to required so that the user must provide an answer. If the answer is no then the second question is not required.

I'm using definitions to define my questions, and then referencing them below in the main question schema. I read that by using the if-then-else feature provided in draft-07 I could use it to set certain questions to be required based on answers to other questions.

In this particular instance what I would like to happen is that if the user enters the answer Home improvements (General) for question 9, then question 257 will be set to required and MUST be answered, otherwise an error should be thrown.

At the moment, when I enter this validator into https://www.jsonschemavalidator.net/ it does not work as expected. What actually happens is the answer for question 257 can be left blank even if the answer to question 9 is "Home improvements (General)

How can I change my schema to give the behaviour I am trying to get?

JSON Schema

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "definitions": {
    "question3-9": {
      "type": "object",
      "properties": {
        "answer": {
          "type": "string",
          "enum": [
            "Home improvements (General)",
            "Other"
          ]
        }
      }
    },
    "question3-257": {
      "type": "object",
      "properties": {
        "answer": {
          "type": "string",
        }
      }
    }
  },
  "type": "object",
  "properties": {
    "form_submission": {
      "type": "object",
      "properties": {
        "sections": {
          "type": "object",
          "properties": {
            "3": {
              "type": "object",
              "properties": {
                "questions": {
                  "type": "object",
                  "properties": {
                    "9": {
                      "$ref": "#/definitions/question3-9"
                    },
                    "257": {
                      "$ref": "#/definitions/question3-257"
                    }
                  },
                  "if": {
                    "properties": {
                      "9": {
                        "properties": {
                          "answer": {
                            "enum": [
                              "Home improvements (General)"
                            ]
                          }
                        }
                      }
                    }
                  },
                  "then": {
                    "required": [
                      "257"
                    ]
                  }
                }
              }
            }
          },
          "required": [
            "3"
          ]
        }
      }
    }
  }
}

JSON to be validated:

{
  "form_submission": {
    "sections": {
      "3": {
        "questions": {
          "9": {
            "answer": "Home improvements (General)",
          },
          "257": {
            "answer": "",
          }
        }
      }
    }
  }
}

Updated If-Then

"if": {
  "properties": {
    "9": {
      "properties": {
        "answer": {
          "enum": [
            "Home improvements (General)"
          ]
        }
      },
      "required": ["answer"]
    }
  },
  "required": ["9"]
},
"then": {
  "257": {
    "properties":{
      "answer":{
        "minLength": 1
      }
    }
  }
}
Relequestual
  • 11,631
  • 6
  • 47
  • 83
Jake12342134
  • 1,539
  • 1
  • 18
  • 45
  • https://stackoverflow.com/questions/38717933/jsonschema-attribute-conditionally-required – tom redfern Jan 29 '19 at 13:29
  • The OP did not have a problem with the applicability, but rather missunderstood how `required` is applied, and that the value of `then` must be a schema. – Relequestual Jan 30 '19 at 09:01

1 Answers1

15

Your problem here is you are expecting required to check the value of the key, which it does not.

Required from the current draft-7 specification:

An object instance is valid against this keyword if every item in the array is the name of a property in the instance.

This means required only checks that the key exists for the object. It is not related to the value. For string validation, see the validation key words which are applicable to strings. I suspect you want minLength or pattern (which is regex).

https://datatracker.ietf.org/doc/html/draft-handrews-json-schema-validation-01#section-6.3

Community
  • 1
  • 1
Relequestual
  • 11,631
  • 6
  • 47
  • 83
  • Hi, I've updated my If-Then within my schema, but it still does not seem to be enforcing the minLength of question 257's answer properly. Am I referencing the `answer` field properly within my then clause? I have updated the OP with my new If-Then at the bottom. – Jake12342134 Jan 30 '19 at 08:33
  • OK. I've debugged the schema by first testing your `if` condition evaluation by making `then` equal `false`. The value of `then` must be a schema... so if you were to take the value of `then` on it's own, you'll see it doesn't add any validation cinstraints, because you need to wrap "257" within `properties`. – Relequestual Jan 30 '19 at 09:00
  • 2
    very nice answer. Difference between `required` and `string contraints`. Just as a ps, `required` is enforced if the field is `null`, but not when is empty. This answer should be selected as correct answer, if you ask me. – myuce Mar 24 '20 at 10:35