JSON 架构:我可以使用比架构根更深的 "if" 吗?

JSON Schema: Can I use "if" deeper than root of schema?

我想像这样验证对象

{
  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 进行验证。

你是对的,你不能将验证应用到你的数据的不同部分而不是你的子方案被应用的地方。让我解释一下。

处理 JSON 模式时发生的第一件事是将整个模式“应用”到整个实例。

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

举个例子,在你的架构中,properties > type 处的子架构应用于实例位置 type,这意味着对象键 type 的值。如果 type 在您的数据中不存在,那么您架构中的子架构将不会执行任何操作(它不会应用于任何地方)。

这大致是模式针对实例的处理模型。希望这可以解释为什么您不能按照您期望的方式工作。但是还是有可能达到你想要的效果。

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

您需要做的是在顶层使用 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"
          }
        }
      }
    }
  }
}

如果您还想确保 typeuserid 存在,那么您还需要在 then 中添加 required: ['id'] ] 子模式。 (如果你也想检查 uuid,你需要在 else 子句中做类似的事情。