0

I am a big fan of python jsonshema. I recently found the if/then/else options which I really like.

However, I have a huge problem with it. Let's say I have:

{
    "required": ["PROP1"],
    "additionalProperties": True,
    "properties": { 
        "PROP1": {"enum": ["PROP1_CHOICE1", "PROP1_CHOICE2"]}
    },
    "allOf": [
        {
            "if": {
                "properties": {
                     "PROP1": {"enum": ["PROP1_CHOICE1"]}
                }
            },
            "then": {
                "required": ["PROP2"],
                "properties": {
                    "PROP2": {"type": "string"},
                }
            },
            "else": False
        },
        {
            "if": {
                "properties": {
                     "PROP1": {"enum": ["PROP1_CHOICE2"]}
                }
            },
            "then": {
                "required": ["PROP2"],
                "properties": {
                    "PROP2": {"type": "boolean"},
                }
            },
            "else": False
        },
    ]
}

Now assuming I test the following file:

{
    "PROP1": "PROP1_CHOICE1",
    "PROP2": true
}

I get an error as expected, which is:

jsonschema.exceptions.ValidationError: False schema does not allow {'PROP1': 'PROP1_CHOICE1', 'PROP2': True}

Failed validating None in schema['allOf'][1]:
    False

On instance:
    {'PROP1': 'PROP1_CHOICE1', 'PROP2': True}

However what I would really like is to obtain the error as if my "PROP_CHOICE2" would not be present in the if/then/else statement, which would be:

jsonschema.exceptions.ValidationError: True is not of type 'string'

Failed validating 'type' in schema['allOf'][0]['then']['properties']['PROP2']:
    {'type': 'string'}

On instance['PROP2']:
    True

I did find a work around for this which is to execute the if/then/else statements sequentially like this:

{
        "required": ["PROP1"],
        "additionalProperties": True,
        "properties": { 
            "PROP1": {"enum": ["PROP1_CHOICE1", "PROP1_CHOICE2"]}
        },
        "if": {
            "properties": {
                "PROP1": {"enum": ["PROP1_CHOICE1"]}
            }
        },
        "then": {
            "required": ["PROP2"],
            "properties": {
                "PROP2": {"type": "string"},
            }
        },
        "else": {
            "if": {
                "properties": {
                        "PROP1": {"enum": ["PROP1_CHOICE2"]}
            }
            },
            "then": {
                "required": ["PROP2"],
                "properties": {
                    "PROP2": {"type": "boolean"},
                }
            },
            "else": False
        }
}

This does resolve my issue but now the issue becomes the indentation level which can quickly increase if you have multiple if/then/else statements.

Is there a way to get a code similar to the first code sample of this question with the output of the second code sample (specific error message without increasing indentation level similar to a switch/case statement) ?

Please note that this issue is particularly problematic for big shema (if I keep first code sample than the error can't pinpoint the specific schema issue and if I put in place my solution, then my indentation level becomes crappy).

Greg7000
  • 297
  • 3
  • 15

1 Answers1

0

With the input from @Jason Desrosiers I now get the expected output as desired and found a way to keep the else statements (so I can deal with all forgotten enum options). Here is the new definition:

{
    "required": ["PROP1"],
    "additionalProperties": True,
    "properties": { 
        "PROP1": {"enum": ["PROP1_CHOICE1", "PROP1_CHOICE2", "PROP_CHOICE_3"]}
    },
    "allOf": [
        {
            "if": {
                "properties": {
                     "PROP1": {"const": "PROP1_CHOICE1"}
                }
            },
            "then": {
                "required": ["PROP2"],
                "properties": {
                    "PROP2": {"type": "string"},
                }
            }
        },
        {
            "if": {
                "properties": {
                     "PROP1": {"const": "PROP1_CHOICE2"}
                }
            },
            "then": {
                "required": ["PROP2"],
                "properties": {
                    "PROP2": {"type": "boolean"},
                }
            },
            
        },
        {
            "else": False
        }
    ]
}

Thx @Jason Desrosiers

With this I now get (as expected, Yeah!):

jsonschema.exceptions.ValidationError: True is not of type 'string'

Failed validating 'type' in schema['allOf'][0]['then']['properties']['PROP2']:
    {'type': 'string'}

On instance['PROP2']:
    True

And let's say I try forgotten "PROP_CHOICE_3" if statement I now get:

jsonschema.exceptions.ValidationError: 'PROP1_CHOICE3' is not one of ['PROP1_CHOICE1', 'PROP1_CHOICE2', 'PROP_CHOICE_3']

Failed validating 'enum' in schema['properties']['PROP1']:
    {'enum': ['PROP1_CHOICE1', 'PROP1_CHOICE2', 'PROP_CHOICE_3']}

On instance['PROP1']:
    'PROP1_CHOICE3'
Greg7000
  • 297
  • 3
  • 15