Json Схема: проверка типа в зависимости от того, где он используется - PullRequest
1 голос
/ 08 мая 2020

Я хотел бы определить схему с типом, требуемый набор которого зависит от того, где он используется.

Простой пример, у нас есть letter, который содержит sender и recipient, очень похожие объекты. Наивным решением было бы просто определить для них разные типы:

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

Можно ли определить это, объединив классы sender и recipient в один, и требуя только поля isDomestic, если адрес используется как recipient?

* В случае вопросов XY: хотя дублирование класса с незначительной разницей в этом простом случае нормально, вложение может привести к тому, что это решение приведет к большому дублированию кода (представьте, что letter содержит два person объекты, каждый из которых имеет address, единственная разница во всей иерархии состоит в том, что один address содержит senderZipCode, а другой receiverZipCode).

1 Ответ

2 голосов
/ 08 мая 2020

Вы можете сделать это с помощью ключевого слова 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"
                }
            }
        }
    }
}
...