【问题标题】:Validate an item in `object` based on another item in the same `object`根据同一“对象”中的另一个项目验证“对象”中的项目
【发布时间】:2021-08-04 15:40:22
【问题描述】:

[可在 https://www.jsonschemavalidator.net 复制 - 只需复制并粘贴 JSON 对象(注意第一个是示例)]

所以,我希望有一个这样的 JSON 对象:

[
    {"k": "my_date", "v": "2021-08-04"},
    {"k": "item_1", "v": 1},
    {"k": "item_2", "v": 2.5},
    ...
    {"k": ".+", "v": <<type - number>>}
]

我想设计一个 JSON 模式,确保“my_date”始终为 string,但所有其他项目(无论其“k”值如何)都是数字。

我现在拥有的是

{
  "$id": "#/properties/my-output",
  "type": "array",
  "title": "The Output Schema",
  "items": {
    "type": "object",
    "properties": {
      "k": {
        "type": "string"
      },
      "v": {
        "type": "number"
      }
    }
  }
}

但这显然行不通,因为

[
  {
    "k": "my_date",
    "v": "2021-08-04"
  },
  {
    "k": "any_name",
    "v": 123.2
  },
  {
    "sdf": "sdf"
  }
]

失败,因为:

  1. my_date 的值为 string,这是架构不允许的;
  2. sdf 根本不应该在这里,但架构接受它。

我应该如何设计架构?

附:我希望会有其他“k”值应该有strings 作为“v”值,所以我希望能够解决这些问题。

【问题讨论】:

    标签: json jsonschema json-schema-validator


    【解决方案1】:

    您可以通过"additionalProperties": false(与“properties”关键字相邻)阻止使用额外的“sdf”属性。见https://json-schema.org/understanding-json-schema/reference/object.html#additional-properties

    至于您的日期,您似乎在说它们都可以是字符串,也不能是字符串,所以我不确定实际的问题是什么。

    【讨论】:

      【解决方案2】:

      原来答案是使用 if-else-then 语句,像这样(感谢@Ether 建议使用additionalProperties):

      {
        "$id": "#/properties/my-output",
        "type": "array",
        "title": "The Output Schema",
        "items": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "k": {
              "type": "string",
            },
            "v": {
            }
          },
          "if": {
            "properties": {
              "k": {
                "enum": ["my_date"]
              }
            }
          },
          "then": {
            "properties": {
              "v": {
                "type": "string"
              }
            }
          },
          "else": {
            "properties": {
              "v": {
                "type": "number"
              }
            }
          }
        }
      }
      

      这里发生的情况如下: 最初,我们希望数组中的项目具有k 值和v 值。 k 值被限制为字符串 - 总是;但我们还没有为 v... 指定约束条件。

      然后,我们明确指定我们的约束:如果k"enum":["my_date", &lt;&lt;add others here&gt;&gt;] 之一,那么我们希望k 的类型为string。否则 - 我们想要一个数字。

      上述架构在以下测试输入中正确失败(您可以在 https://www.jsonschemavalidator.net 上尝试):

      [
        {
          "k": "my_date",
          "v": "2021-08-04"
        },
        {
          "k": "my_date_wrong",
          "v": "2021-08-04"
        },
        {
          "k": "some_item",
          "v": 123.2
        },
        {
          "k": "some_other_123item",
          "v": 123.2
        },
        {
          "sdf": "sdf"
        }
      ]
      

      上述输入在"k": "my_date_wrong" 上正确失败,因为它不包含在 if 语句的enum 中。它在sdf 字段上也正确失败,因为它被additionalProperties 无效。

      这种方法的明显缺点是,如果您有许多必须是字符串的v-s,则需要在 if 语句中显式枚举它们。

      【讨论】:

        【解决方案3】:

        因此,一种方法是使用“oneOf”作为数组中项目的架构。

        {
           "type": "object",
            "required": ["k", "v"],
              "properties": {
                "k": {
                  "type": "string"
                },
                "v": {}
              },
            "additionalProperties": false,
            "oneOf": [
              {"$ref": "#/$defs/dateValue"},
              {"$ref": "#/$defs/anyOtherValue"}
            ],
            "$defs":{
              "dateValue": {
                  "properties": {
                    "k": {
                      "const": "my_date"
                    },
                   "v": { "type": "string" }
                  },
                  "additionalProperties": false
              },
              "anyOtherValue": {
                  "not": {
                    "properties": {
                      "k": {
                        "enum": ["my_date"]
                      }
                    }
                 }
              }
            }
        }
        

        【讨论】:

        • (这种方法的优点是您可以通过将特定模式添加到“oneOf”列表以及“枚举”列表的键值轻松地将其扩展到其他键控类型在“任何其他值。)
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-03-22
        • 2018-03-19
        • 2019-10-31
        • 2022-01-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多