4
votes

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
      }
    }
  }
}
1
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

1 Answers

6
votes

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://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.3