2

I have a JSON:

{
    "i0": {
        "j0": {
            "a0": true
        }
    },
    "i1": {
        "j1": {
            "a1": "stuff"
        }
    }
}

I want a validation: If a0 is true, a1 should be required.

My schema is currently:

{
    "$schema": "http://json-schema.org/draft-07/schema",
    "id": "id",
    "type": "object",
    "required": [
        "i0",
        "i1"
    ],
    "allOf": [
        {
            "if": {
                "properties": {
                    "i0": {
                        "j0": {
                            "a0": true
                        }
                    }
                }
            },
            "then": {
                "properties": {
                    "i1": {
                        "j1": {
                            "required": [
                                "a1"
                            ]
                        }
                    }
                }
            }
        }
    ]
}

This conditional seems to not actually be run. Alternatively, I have have seen gotten a very similar conditional to work if I try to put the required on the same level as the value I am checking. As in:

"allOf": [
    {
        "if": {
            "a0": true
        },
        "then": {
            "required": [
                "a1"
            ]
        }
    }
]

but this would require a1 to be under j0 along with a1. How do I require an object under j1 based on a value under j0?

swinters
  • 337
  • 3
  • 5
  • 16

1 Answers1

5

Try this:

{
  "if":{
    "type":"object",
    "properties":{
      "i0":{
        "type":"object",
        "properties":{
          "j0":{
            "type":"object",
            "required":["a0"]
          }
        },
        "required":["j0"]
      }
    },
    "required":["i0"]
  },
  "then":{
    "type":"object",
    "properties":{
      "i1":{
        "type":"object",
        "properties":{
          "j1":{
            "type":"object",
            "required":["a1"]
          }
        },
        "required":["j1"]
      }
    },
    "required":["i1"]
  }
}

You have to use the overall structure within the if/then keywords, starting with whatever common root they have. In this case, their paths begin to diverge at the i0/i1 property, so you have to include the entire structure from that point.

The type keywords ensure that you have an object, otherwise the schema could pass validation when other types, like strings or booleans, are used.

The required keywords ensure that the if/then subschemas only match on objects which actually contain the i0.j0.a0/i1.j1.a1 property paths, respectively.

Additionally, the required keywords for the a0/`a1 properties only specify that they exist. You can add more validation to that subschema if you need it.

gregsdennis
  • 7,218
  • 3
  • 38
  • 71
  • 2
    Highlighting that you need to repeat the "properties" keyword at every level like you did - if not, like the OP did, "j1" and "a0" are treated as unknown/extension keywords that are simply not evaluated, instead of as property names. Because Json schema allows unknown keywords, the OP's schema is still grammatically valid unfortunately, making it hard to find the error. – Erwin Bolwidt Feb 07 '19 at 21:46
  • 1
    The value of a key in the `properties` key word must be a JSON Schema. In furture, consider testing the value of each key from your `properties` key words. =] – Relequestual Feb 08 '19 at 09:12