Home > other >  How to specify in JSON Schema one property or the other but not both?
How to specify in JSON Schema one property or the other but not both?

Time:06-18

I have 4 properties: A, B, C, and D.

I'd like to have either A or B. One of them must exist. For this I created this schema that works fine.

  "oneOf": [
    {
      "required": ["A"]
    },
    {
      "required": ["B"]
    }
  ],

Now, I'd like to have C and D included but in a sense that I either have C or D but not both. And I can have neither. In other words, if I'm going to include C, then I can't include D and vice versa. However, I can also decide not to include either of them.

Something like this in my file.json

{
  "A": "Prop",
  "C": "Prop"
}

OR

{
  "B": "Prop",
  "D": "Prop"
}

OR

{
  "B": "Prop"
}

The following should not be allowed

You can't have A and B together.

{
  "A": "Prop",
  "B": "Prop"
}

You can't have both C and D together. But, as mentioned above, you don't have to have one of them either.

{
  "C": "Prop",
  "D": "Prop"
}

CodePudding user response:

I'm only passingly familiar with JSON schema. But assuming you can nest subschema, just write it out logically and then translate it to Boolean algebra. Then XOR is oneOf, OR is anyOf, AND is allOf, and NOT is not.

You want at one or more of these to be true:

  1. A or B but not both
  2. C or D but not both
  3. Nothing at all. Or, "not anything".

That's:

(A XOR B) OR (C XOR D) OR NOT (A OR B OR C OR D)

That's:

anyOf(
    oneOf([A], [B]),
    oneOf([C], [D]),
    not(anyOf([A],[B],[C],[D]))
)

CodePudding user response:

I ended up doing this:

  "oneOf": [
    {
      "required": ["A"],
      "dependencies": {
        "C": {
          "not": {
            "required": ["D"]
          }
        },
        "D": {
          "not": {
            "required": ["C"]
          }
        }
      }
    },
    {
      "required": ["B"],
      "dependencies": {
        "C": {
          "not": {
            "required": ["D"]
          }
        },
        "D": {
          "not": {
            "required": ["C"]
          }
        }
      }
    }
  ],
  • Related