【问题标题】:JSON Schema: Can I use "if" deeper than root of schema?JSON Schema:我可以使用比模式根更深的“if”吗?
【发布时间】:2020-07-17 08:19:20
【问题描述】:

我想验证这样的对象

{
  type: "user",
  data: {id: 1},
}

{
  type: "account",
  data: {uuid: "xxxx"},
}

我以为我可以这样写架构

{
  type: "object",
  properties: {
    type: {enum: ["user", "account"]},
    data: {
      "if": {properties: {type: {const: "user"}}},
      "then": {
        type: "object",
        properties: {
          id: {type: "number"}
        }
      },
      "else": {
        type: "object",
        properties: {
          uuid: {type: "string"}
        }
      },
    }
  }
}

但看起来我无法从 data 字段的上下文中引用根 type 字段。所以我有两个问题。我可以使用比 root 更深的 if 吗?如果可以,那么如何从嵌套对象引用父对象或根对象?我正在使用节点ajv 进行验证。

【问题讨论】:

    标签: jsonschema ajv


    【解决方案1】:

    您是对的,您不能将验证应用于数据的不同部分,而不是应用子方案的位置。让我解释一下。

    在处理 JSON Schema 时发生的第一件事就是将整个 Schema 作为一个整体“应用”到整个实例。

    properties 是一个应用程序关键字,因为它本身不声明任何验证规则。 properties 对象的 VALUES 是子模式(它们本身就是模式),当关联的 KEY 匹配时,它们将应用于实例位置值。

    举个例子,在您的架构中,properties > type 的子架构应用于实例位置 type,这意味着对象键 type 的值。如果type 不存在于您的数据中,则您的架构中的子架构不会做任何事情(它不会在任何地方应用)。

    这大致是 Schema 针对实例的处理模型。希望这能解释为什么你不能按照你期望的方式工作。但是,仍然可以实现您想要的。

    thenelse是条件应用关键字,所以需要按照相同的模型应用。

    您需要做的是在顶层使用ifthenelse,但对您想要执行的验证进行深度/嵌套应用。

    这是一个带有新架构和实例的演示 https://jsonschema.dev/s/sejHF

    {
      "$schema": "http://json-schema.org/draft-07/schema",
      "type": "object",
      "properties": {
        "type": {
          "enum": [
            "user",
            "account"
          ]
        },
        "data": {}
      },
      "if": {
        "properties": {
          "type": {
            "const": "user"
          }
        }
      },
      "then": {
        "type": "object",
        "properties": {
          "data": {
            "properties": {
              "id": {
                "type": "number"
              }
            }
          }
        }
      },
      "else": {
        "type": "object",
        "properties": {
          "data": {
            "properties": {
              "uuid": {
                "type": "string"
              }
            }
          }
        }
      }
    }
    

    如果您还想确保typeuser 时存在id,那么您还需要在then 子模式中添加required: ['id']。 (如果您也想检查 uuid,则需要在 else 子句中执行类似操作。

    【讨论】:

      猜你喜欢
      • 2019-09-09
      • 1970-01-01
      • 2023-02-01
      • 2013-07-12
      • 2015-04-04
      • 2011-11-22
      • 2018-11-16
      • 1970-01-01
      • 2019-10-12
      相关资源
      最近更新 更多