首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >带有可选项的JSON架构数组元组验证

带有可选项的JSON架构数组元组验证
EN

Stack Overflow用户
提问于 2022-01-12 16:17:22
回答 2查看 536关注 0票数 2

我正在编写一个JSON模式,它能够验证数组中的每个项目都有不同的架构,每个项目的序号索引都是有意义的。,但有些项是可选的。

但是,使用当前的规范(2020-12),我不能对可选项使用prefixItems。要明确:

  • 所有必需项都应存在,并应根据索引匹配模式进行验证。
  • 缺少可选项不应使结果无效。
  • 现有的可选项应根据索引匹配架构进行验证。

下面是我试图验证的数据的一个示例:

(没有可选数组元素)

代码语言:javascript
复制
[
    {
        "name": "Document 1 required",
        "url": "random.random/12313213.pdf"
    },
    {
        "name": "Document 2 required",
        "url": "random.random/12313213.pdf"
    }
]

(带有可选数组元素)

代码语言:javascript
复制
[
    {
        "name": "Document 1 required",
        "url": "random.random/1231322313.pdf"
    },
    {
        "name": "Optional document 1",
        "url": "random.random/1231356213.pdf"
    },
    {
        "name": "Document 2 required",
        "url": "random.random/1231893213.pdf"
    },
    {
        "name": "Optional document 2",
        "url": "random.random/1231336213.pdf"
    }
]

下面是我使用的当前模式:

代码语言:javascript
复制
{
    "type": "array",
    "items": false,
    "prefixItems": [
        {
            "type": "object",
            "properties": {
                "name": {
                    "type": "string",
                    "const": "Document 1 required"
                },
                "url": {
                    "type": "string",
                    "format": "uri"
                }
            }
        },
        {
            "type": "object",
            "properties": {
                "name": {
                    "type": "string",
                    "const": "Document 2 required"
                },
                "url": {
                    "type": "string",
                    "format": "uri"
                }
            }
        }
    ]
}

我尝试过用正确的模式和存根oneOf在可选项位置添加一个{},但它似乎不起作用:

代码语言:javascript
复制
{
    "type": "array",
    "items": false,
    "prefixItems": [
        {
            "type": "object",
            "properties": {
                "name": {
                    "type": "string",
                    "const": "Document 1 required"
                },
                "url": {
                    "type": "string",
                    "format": "uri"
                }
            }
        },
        {
            "oneOf": [
                {
                    "type": "object",
                    "properties": {
                        "name": {
                            "type": "string",
                            "const": "Optional document 1"
                        },
                        "url": {
                            "type": "string",
                            "format": "uri"
                        }
                    }
                },
                {}
            ]
        },
        {
            "type": "object",
            "properties": {
                "name": {
                    "type": "string",
                    "const": "Document 2 required"
                },
                "url": {
                    "type": "string",
                    "format": "uri"
                }
            }
        },
        {
            "oneOf": [
                {
                    "type": "object",
                    "properties": {
                        "name": {
                            "type": "string",
                            "const": "Optional document 2"
                        },
                        "url": {
                            "type": "string",
                            "format": "uri"
                        }
                    }
                },
                {}
            ]
        }
    ]
}

还尝试了使用containsadditionalItems的不同方法。但是,它们要么不适用于多个模式,要么不保证可选项的顺序。

注意:该示例使用类似的模式,这些模式可以简化,但用于展示问题所在。

编辑:

正如@Relequestual所指出的,问题在于我试图将元组验证与列表验证相结合,其中数据具有任意长度(必需+可选)和每个项的特定模式。这在当前版本的JSON架构规范中是不可能实现的。

EN

回答 2

Stack Overflow用户

发布于 2022-01-18 19:34:55

您的模式无法工作,因为模式{}始终是真的--因此,当您说"oneOf": [ { .. some schema .. }, {} ]时,本质上是否定第一个模式--因为第二个模式必须始终为真,第一个模式必须为假。这和你想要的正好相反!

我认为你期望prefixItems比实际情况更复杂。prefixItems列表中的每个模式都是可选的,也就是说,如果数据实例中没有相应的项,则不会出现故障。

例如,考虑根据此模式验证此数据[1]

代码语言:javascript
复制
{
  "prefixItems": [
    { "type": "integer" },
    false
  ]
}

该评估的总体结果是true --第一个数据元素对"type": integer进行验证,而第二个模式false从不运行,因为没有可以运行的项。如果我们通过了[ 1, 1 ]的数据实例,那么验证就会失败。

如果您想确保所有对应于prefixItems子模式的数据项都实际存在,那么您将需要使用minItems:例如,对于上面的示例,您将添加"minItems": 2

一个主要的警告是,你需要把你所有需要的东西放在第一位。不能在所需项之间交错可选项,因为prefixItems中的模式总是按顺序应用,而且如果其中一个模式没有计算为真,则不会“跳过”项到下一个模式。第一个prefixItems模式总是应用于第一个数据实例,第二个prefixItems模式总是应用于第二个数据实例,依此类推。

另一方面,如果您可以完全不指定订单,则可以使用多个contains指令(注意,如果没有显式提供,minContains默认为1):

代码语言:javascript
复制
"allOf": [
  { "contains": { schema for one of the required items, that can be anywhere... },
  { "contains": { schema for another required item... },
  { "minContains": 0, "contains": { schema for an optional item... },
  ...
]

还可以使用additionalItems将可选项放入anyOf中(即使可选项的数量非常大或不可预测):

代码语言:javascript
复制
"additionalItems": {
  "anyOf": [
    { ..schema of an optional item.. },
    { "" },
    ...
  ]
}
票数 3
EN

Stack Overflow用户

发布于 2022-01-19 08:46:30

如果可以将所有强制性非可选项移动到数组前面,则可以使用prefixItems按顺序定义所需项,然后使用additionalItems为所有其他(可选)项定义一个模式,前提是附加选项是一致的。

使用minItems确保存在所需的项目数。可以使用maxItems限制数组中的总项数,如果需要的话,可以有效地限制可选项的数量。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70684901

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档