0

I have been trying to get my JSON schema right. I have a boolean property based on which I have to determine the required properties. Below is my sample JSON which I want to fail the validation with item3 not present.

{
  "item1": true,
  "item2": "ABC"
}

This is the JSON which I want the validation to pass

{
  "item1": true,
  "item2": "ABC",
  "item3": {
    "subItem1": "ABC",
    "subItem2": "BAC"
  }
}

Similarly, if the item1 is false, then the validation should pass for both the above JSON's.

My JSON schema for the same is as below.

{
    "definitions": {},
    "type": "object",
    "title": "The Root Schema",
    "properties": {
        "item1": {
            "$id": "#/properties/item1",
            "type": "boolean",
            "title": "The Item1 Schema",
            "default": false,
            "examples": [
                true
            ]
        },
        "item2": {
            "$id": "#/properties/item2",
            "type": "string",
            "title": "The Item2 Schema",
            "default": "",
            "examples": [
                "ABC"
            ],
            "pattern": "^(.*)$"
        },
        "item3": {
            "$id": "#/properties/item3",
            "type": "object",
            "title": "The Item3 Schema",
            "required": [
                "subItem1",
                "subItem2"
            ],
            "properties": {
                "subItem1": {
                    "$id": "#/properties/item3/properties/subItem1",
                    "type": "string",
                    "title": "The Subitem1 Schema",
                    "default": "",
                    "examples": [
                        "AAA"
                    ],
                    "pattern": "^(.*)$"
                },
                "subItem2": {
                    "$id": "#/properties/item3/properties/subItem2",
                    "type": "string",
                    "title": "The Subitem2 Schema",
                    "default": "",
                    "examples": [
                        "BAC"
                    ],
                    "pattern": "^(.*)$"
                }
            }
        }
    },
    "required": ["item1"],
    "allOf": [{
        "if": {
            "properties": {
                "item1": {
                    "enum": [
                        true
                    ]
                }
            }
        },
        "then": {
            "required": [
                "item2",
                "item3"
            ]
        },
        "else": {
            "required": [
                "item2"
            ]
        }
    }]
}

My validation always fails.

If item1 is true, subItem2 should be required. If item1 is false, then item3 is not required, but should still validate if included.

Relequestual
  • 11,631
  • 6
  • 47
  • 83
ZZzzZZzz
  • 1,800
  • 3
  • 29
  • 51
  • What I see in your schema is, if item1 is true, then item2 and item3 are required, otherwise, only item2 is required. Is that your intent? I'm not totally clear what your goal is. Could you provide example JSON you want to validate successfully and example JSON you want to fail validation please? – Relequestual Apr 25 '19 at 08:09
  • I have added a sample JSON in the description. Just the toggle change is from true to false. @Relequestual – ZZzzZZzz Apr 25 '19 at 12:48
  • 1
    From your description of what you want in your question, it looks like you have your `then` and `else` the wrong way round, but I can't tell because your schema and what you say you want seems to be in contradiction. Hence why I asked if you could provide JSON you want to pass and fail, because currently it's unclear. – Relequestual Apr 25 '19 at 12:51
  • @RelequestualAdded the JSON samples – ZZzzZZzz Apr 25 '19 at 13:16
  • Your if/then/else block works correctly in terms of validation. The example JSON you provided that you expect to pass, fails, because you have required that `item3` has a property of `subItem1` and `subItem2`, but it does not. – Relequestual Apr 25 '19 at 13:43
  • You can run quick checks using https://www.jsonschemavalidator.net/ – Relequestual Apr 25 '19 at 13:43
  • @Relequestual How to handle that kind of case? I need `subItem1` and `subItem2` also to be based on the requirement of `Item3`. – ZZzzZZzz Apr 25 '19 at 14:55
  • You fixed your example JSON and now it passes as you requested. If you have further questions, I'd ask you consider asking a new question, because I've solved the issue you presented with the schema and instances provided. (If you change the question, it's going to get confusing for others.) – Relequestual Apr 25 '19 at 15:01
  • Alternatively, if you wish to discuss this in longer form, please join the JSON Schema slack via json-schema.org. Happy to help. – Relequestual Apr 25 '19 at 15:04

1 Answers1

1

Your if/then/else block works correctly in terms of validation.

The example JSON you provided that you expect to pass, fails, because you have required that item3 has a property of subItem1 and subItem2, but it does not.

Now you've updated your example JSON that should pass to correct item3 containing subItem1 and subItem2, the validation passes with the schema you've provided.


Additionally, you want, If I understand correctly:

If item1 is true, subItem2 should be required. If item1 is false, then item3 is not required, but should still validate if included.

Move the schema that makes subItem3 required from item3 to your then clause. This will make it so subItem3 is only "required" if your if schema validates successfully (item1 is true)

{
  "definitions": {},
  "type": "object",
  "title": "The Root Schema",
  "properties": {
    "item1": {
      "$id": "#/properties/item1",
      "type": "boolean",
      "title": "The Item1 Schema",
      "default": false,
      "examples": [
        true
      ]
    },
    "item2": {
      "$id": "#/properties/item2",
      "type": "string",
      "title": "The Item2 Schema",
      "default": "",
      "examples": [
        "ABC"
      ],
      "pattern": "^(.*)$"
    },
    "item3": {
      "$id": "#/properties/item3",
      "type": "object",
      "title": "The Item3 Schema",
      "required": [
        "subItem1"
      ],
      "properties": {
        "subItem1": {
          "$id": "#/properties/item3/properties/subItem1",
          "type": "string",
          "title": "The Subitem1 Schema",
          "default": "",
          "examples": [
            "AAA"
          ],
          "pattern": "^(.*)$"
        },
        "subItem2": {
          "$id": "#/properties/item3/properties/subItem2",
          "type": "string",
          "title": "The Subitem2 Schema",
          "default": "",
          "examples": [
            "BAC"
          ],
          "pattern": "^(.*)$"
        }
      }
    }
  },
  "required": [
    "item1"
  ],
  "allOf": [
    {
      "if": {
        "properties": {
          "item1": {
            "enum": [
              true
            ]
          }
        }
      },
      "then": {
        "required": [
          "item2",
          "item3"
        ],
        "properties": {
          "item3": {
            "required": [
              "subItem2"
            ]
          }
        }
      },
      "else": {
        "required": [
          "item2"
        ]
      }
    }
  ]
}
Relequestual
  • 11,631
  • 6
  • 47
  • 83
  • If `Item3` is required then all the subItems as required. Else, the requirement under the `Item3` should be nullified. – ZZzzZZzz Apr 25 '19 at 15:13
  • This is currently what happens. In your example JSON you expect to pass, if you remove item3`, validation fails because `item1` is true, which triggers the `then` block of your `if` block, which then makes `item3` required, and therefore you fail validation. – Relequestual Apr 25 '19 at 15:17
  • If you have additional JSON pass / fail examples which are not working as you expect, please share them, and test using https://www.jsonschemavalidator.net – Relequestual Apr 25 '19 at 15:18
  • `{ "item1": true, "item2": "ABC", "item3": { "subItem1": "ABC", "subItem2": "BAC" } }` This JSON fails the requirement of subItems if item3 is required. – ZZzzZZzz Apr 25 '19 at 15:28
  • This passes validation. You said in your question that you expected that JSON instance to pass validation. I'm confused. – Relequestual Apr 25 '19 at 15:39
  • It asses the validation. But, try removing one of the subItem for a true case? It dosent work. – ZZzzZZzz Apr 25 '19 at 16:29
  • 1
    Removing either of the subitems causes validation to fail. Isn't that what you expect? – Relequestual Apr 25 '19 at 22:13
  • Then it does work according to how you expect. What "doesn't work"? – Relequestual Apr 26 '19 at 12:54
  • If `Item1` is `false`, then `Item3` is not required, but, it could be provided as part of the request. If provided, there are required subItems in the request. That should be validated based on the `Item1` flag and not be made mandatory, where as if Item3 has required fields on subItems, then even when `Item3` is not required, the validation fails due to the required subItems. – ZZzzZZzz Apr 26 '19 at 15:22
  • 1
    OK! Solved. Will update your question, followed by my answer. – Relequestual Apr 26 '19 at 15:26