当元素是可选的时,如何在json模式中定义choice元素?

时间:2014-11-20 19:50:37

标签: json jsonschema

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

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

在上面的模式中,我想在城市和州之间创建一个选择。无论是城市还是州都可以来json。所以json下面会无效

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

以下一个应该是有效的

{
    "street_address": "abc"
}

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

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

有人可以帮我修改上面的架构来完成目标。

4 个答案:

答案 0 :(得分:5)

使用" oneOf"当只有一个替代品应该持有时," anyOf"当至少有一个替代方案应该成立时。

您不需要在oneOf内重复共同属性。实现目标的最短途径是:

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

答案 1 :(得分:1)

您需要使用" oneOf"。像这样:

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

您会注意到,它有点重复。因为,在您的示例中,您只提供"类型"对于每个房产,重复都不是那么糟糕。但是,如果您有更复杂的属性,则可以考虑使用deifinitions仅在顶部定义每个属性一次,然后使用$ref来引用定义。 Here's a good article on that

答案 2 :(得分:1)

这是一个满足所有四个条件的模式:

    {
        "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
    }

答案 3 :(得分:0)

我发现p3属性对于此用例很有用。

示例:

function func(obj: p4) {
    if ('b' in obj) {
        obj.a.toFixed() // error now
    }

    if (obj.b !== undefined) {
        obj.a.toFixed(); // okay
    }
}

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

希望有帮助。