在 JSONSchema 中,如何验证模式至少具有两个属性之一?

时间:2021-05-21 10:07:53

标签: json jsonschema

现在已经有几个问题要求类似的问题,但我找不到与我想要的完全匹配的问题。

{
    "$schema": "http://json-schema.org/draft-07/schema",
    "title": "Example schema",
    "type": "object",
    "properties": {
        "youtubeLink": {
            "type": "string",
            "pattern": "http(?:s?):\/\/(?:www\\.)?youtu(?:be\\.com\/watch\\?v=|\\.be\/)([\\w\\-\\_]*)(&(amp;)?‌​[\\w\\?‌​=]*)?"
        },
        "assetFile": {
            "type": "string"
        }
    },
    "additionalProperties": false,
    "dependencies": {
        "assetFile": {
            "not": {
                "required": [
                    "youtubeLink"
                ]
            }
        },
        "youtubeLink": {
            "not": {
                "required": [
                    "assetFile"
                ]
            }
        }
    }
}

在示例中,您可以看到两个属性,其中之一是必需的,不多也不少。目前你不能同时放弃这两个属性,但你可以一个都不放弃。我还希望没有其他属性(已经完成)。我知道这可以通过指定最少的属性来完成,但如果您有更复杂的架构,这似乎很麻烦。

如果可能的话,我也希望有一个带有默认值的默认属性,如果两个 props 都没有给出。

2 个答案:

答案 0 :(得分:1)

您可以使用 oneOf 非常干净地表达这一点。 oneOf 断言一个且只有一个给定的架构必须是有效的,架构才能进行验证。

{
  "type": "object",
  "properties": {
    "youtubeLink": {},
    "assetFile": {}
  },
  "additionalProperties": false,
  "oneOf": [
    { "required": ["youtubeLink"] },
    { "required": ["assetFile"] }
  ]
}
  • 如果您只有“youtubeLink”,则 /oneOf/0 将通过,而 /oneOf/1 将失败。 (通过)
  • 如果您只有“assetFile”,则 /oneOf/0 将失败而 /oneOf/1 将通过。 (通过)
  • 如果两者都有,/oneOf/0 将通过,/oneOf/1 将通过。 (失败)
  • 如果没有,/oneOf/0 将失败,/oneOf/1 将失败。 (失败)

答案 1 :(得分:0)

我终于有了一些工作,即使是默认的。但是有没有更短的方法来做到这一点?我是在学习了 JSON Schemas 并尝试了几个小时后才得出这个结果的,所以肯定有更短的东西。

{
    "$schema": "http://json-schema.org/draft-07/schema",
    "title": "Config file validation",
    "description": "validation schema of the config.json file",
    "type": "object",
    "properties": {
        "youtubeLink": {
            "type": "string",
            "pattern": "http(?:s?):\/\/(?:www\\.)?youtu(?:be\\.com\/watch\\?v=|\\.be\/)([\\w\\-\\_]*)(&(amp;)?‌​[\\w\\?‌​=]*)?"
        },
        "assetFile": {
            "type": "string",
            "pattern": "^(/)?([^/\\0\n]+(/)?)+\\.(mp3)$"
        }
    },
    "additionalProperties": false,
    "if": {
        "not": {
            "oneOf": [
                {
                    "required": [
                        "youtubeLink"
                    ]
                },
                {
                    "required": [
                        "assetFile"
                    ]
                }
            ]
        }
    },
    "then": {
        "properties": {
            "youtubeLink": {
                "default": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
            }
        }
    },
    "dependencies": {
        "assetFile": {
            "not": {
                "required": [
                    "youtubeLink"
                ]
            }
        },
        "youtubeLink": {
            "not": {
                "required": [
                    "assetFile"
                ]
            }
        }
    }
}