Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to define choice element in json schema when elements are optional?

------------Josn schema-----------

{
    "type": "object",
    "properties": {
        "street_address": {
            "type": "string"
        },
        "city": {
            "type": "string"
        },
        "state": {
            "type": "string"
        }
    },
    "required": [
        "street_address"
    ],
    "additionalProperties": false
}

In above schema i want to create a choice between city and state. That is either city or state can come in json. So that below json would be invalid

{
    "street_address": "abc",
    "city": "anv",
    "state": "opi"
}

and below one should be valid one

{
    "street_address": "abc"
}

or

{
    "street_address": "abc",
    "city": "anv"
}

or

{
    "street_address": "abc",
    "state": "opi"
}

Can some one please help me to modify above schema to accomplish the goal.

like image 872
javadev Avatar asked Nov 20 '14 19:11

javadev


3 Answers

Use "oneOf" when only one of the alternatives should hold, and "anyOf" when at least one of the alternatives should hold.

You don't need to repeat common properties within oneOf. The shortest way to accomplish your goal would be:

{
    "type" : "object",
    "properties" : {
        "street_address" : {
            "type" : "string"
        },
        "city" : {
            "type" : "string"
        },
        "state" : {
            "type" : "string"
        }
    },
    "oneOf" : [{
            "required" : ["city"]
        }, {
            "required" : ["state"]
        }
    ],
    "required" : [
        "street_address"
    ],
    "additionalProperties" : false
}
like image 104
jruizaranguren Avatar answered Oct 27 '22 09:10

jruizaranguren


Here is a schema that satisfies all four conditions:

    {
        "type": "object",
        "properties": {
            "street_address": {
                "type": "string"
            },
            "city": {
                "type": "string"
            },
            "state": {
                "type": "string"
            }
        },
        "required": [
            "street_address"
        ],
        "anyOf": [{}, {
            "required": ["city"]
        }, {
            "required": ["state"]
        }],
        "not": {
            "required": ["city", "state"]
        },
        "additionalProperties": false
    }
like image 3
Rob Avatar answered Oct 27 '22 10:10

Rob


I found the enum property useful for this use case.

Example:

schema = {
    "type": "array", 
    "items": {
        "enum": ["choice1", "choice2"]
    }
}

validate(
    instance=["choice1"], 
    schema=schema
)
# all good

validate(
    instance=["something-else"], 
    schema=schema
)
# ValidationError

Reference: https://json-schema.org/understanding-json-schema/reference/combining.html#combining-schemas

Hope it helps.

like image 3
Martin Zugnoni Avatar answered Oct 27 '22 09:10

Martin Zugnoni