Json 架构:根据使用位置验证类型

Json Schema: Verifying a type based on where it is used

我想定义一个模式,其所需的集合因使用位置而异。

简单的例子,我们有一个letter,其中包含一个senderrecipient,它们是非常相似的对象。天真的解决方案是为它们定义不同的类型:

{
    "$schema":"http://json-schema.org/draft-07/schema",
    "type":"object",
    "definitions":{
        "sender":{
            "type":"object",
            "properties":{
                "zipCode":{
                    "type":"string"
                },
                "isDomestic" : { 
                    "type" : "boolean"
                }
            },
            "required":[
                "zipCode"
            ]
        },
        "recipient":{
            "type":"object",
            "properties":{
                "zipCode":{
                    "type":"string"
                },
                "isDomestic" : { 
                    "type" : "boolean"
                }
            },
            "required":[
                "zipCode",
                "isDomestic"
            ]
        }
    },
    "properties":{
        "letter":{
            "type":"object",
            "required":[
                "sender",
                "recipient"
            ],
            "properties":{
                "sender":{
                    "$ref":"#/definitions/sender"
                },
                "recipient":{
                    "$ref":"#/definitions/recipient"
                }
            }
        }
    }
}

是否可以通过将 senderrecipient class 合并为一个来定义它,并且如果地址用作一个 recipient?

*在 XY 问题的情况下:虽然在这种简单的情况下复制 class 的细微差别很好,但嵌套会使该解决方案引入大量代码重复(想象 letter持有两个 person 对象,每个对象都有一个 address,整个层次结构中的唯一区别是一个 address 包含一个 senderZipCode 而另一个 receiverZipCode)。

您可以使用 allOf 关键字来做到这一点,并将公共元素提取到新定义中:

{
    "$schema":"http://json-schema.org/draft-07/schema",
    "type":"object",
    "definitions":{
        "sender_or_recipient": {
            "type":"object",
            "properties":{
                "zipCode":{
                    "type":"string"
                },
                "isDomestic" : { 
                    "type" : "boolean"
                }
            },
            "required":[
                "zipCode"
            ]
        },
        "sender":{
            "$ref":"#/definitions/sender_or_recipient"
        },
        "recipient":{
            "allOf":[
                {
                    "$ref":"#/definitions/sender_or_recipient"
                },
                {
                    "required":[
                        "isDomestic"
                    ]
                }
            ]
        }
    },
    "properties":{
        "letter":{
            "type":"object",
            "required":[
                "sender",
                "recipient"
            ],
            "properties":{
                "sender":{
                    "$ref":"#/definitions/sender"
                },
                "recipient":{
                    "$ref":"#/definitions/recipient"
                }
            }
        }
    }
}