JSON 模式中的条件引用

Conditional References in a JSON Schema

我想编写一个文件 JSON 模式定义,其中包含多个我可以组合的子模式,具体取决于负载。

以下架构验证我的架构正在处理我的示例 JSON 响应。 (响应对象 payload.role 的类型错误,以确保模式捕获此错误!)

为清楚起见,我减少了最重要的部分。可以在此处找到完整的工作示例:https://www.jsonschemavalidator.net/s/3KAaXjtg

架构

{
  "$schema": "http://json-schema.org/draft-07/schema",
  "$id": "http://example.com/baseSchema.json",
  "type": "object",
  "required": [
    "payload"
  ],
  "properties": {
    "payload": {
      "$id": "#/properties/payload",
      "type": "object",
      // reference the right schema depending on the payload child key
      // if `payload.user` reference `userSchema.json`
      // if `payload.users` reference `usersSchema.json`
      // if `payload.*` reference `*Schema.json`
      "$ref": "userSchema.json"
    }
  },
  "definitions": {
    "user": {
      "$id": "http://example.com/userSchema.json",
      "type": "object",
      "required": [
        "user"
      ],
      "properties": {
        "user": {
          "type": "object",
          "$ref": "userProperties.json"
        }
      }
    },
    "users": {
      "$id": "http://example.com/usersSchema.json",
      "type": "object",
      "required": [
        "users"
      ],
      "properties": {
        "users": {
          "type": "array",
          "items": {
            "$ref": "userProperties.json"
          }
        }
      }
    },
    "userProperties": {
      "$id": "http://example.com/userProperties.json",
      "type": "object",
      "properties": {
        "firstName": {
          "$id": "#/properties/payload/properties/user/properties/firstName",
          "type": "string"
        }
      }
    }
  }
}

回应

{
  "status": {
    "code": 200,
    "description": "User retrieved successfully."
  },
  "payload": {
    "user": {
      "firstName": "Joe",
      "lastName": "Doe",
      "role": "3", // for testing reasons, this is the wrong type!
      "email": "doe@example.com",
      "customerID": "",
      "projects": [
        "AIXG5mEg6QLl9rhVSE6m",
        "Bs1bHiOIqKclwwis3CNf",
        "NC2OUGVZXU35FA7iwRn4"
      ],
      "status": "Status",
      "id": "c555BSZnKLdHSRYqrU5hqiQo733j13"
    }
  }
}

所以我有一个 baseSchema.json 匹配这个响应:

{
  "status": {},
  "payload": {}
}

payload 通过某个键(例如 payload.user = {}payload.foo = {} 进行扩展,并且根据该键,我想使用我的定义之一扩展架构。

以下部分仅适用于密钥 user:

  "properties": {
    "payload": {
      "$id": "#/properties/payload",
      "type": "object",
      // reference the right schema depending on the payload child key
      // if `payload.user` reference `userSchema.json`
      // if `payload.users` reference `usersSchema.json`
      // if `payload.*` reference `*Schema.json`
      "$ref": "userSchema.json"
    }
  },

我未能设置任何 conditions(使用 allOfifelse),它会根据 payload键。

感谢任何提示和帮助解决这个问题。

Schema 和 link 最后演示...让我们看看我们是如何到达那里的...

在 JSON Schema draft-07 及之前的版本中,您不能将 $ref 与其他关键字一起使用。其他关键字将被忽略。 (在您的架构 http://example.com/userSchema.json 中,$ref 旁边有 type。幸运的是,当您在引用模式中声明类型时,这并没有给您带来任何问题。 (您可以使用 2019-09 或更高版本执行此操作。)

关键字 ifthenelse 的值是架构。 要将 then 子模式应用于您的实例位置,if 模式必须恢复有效。如果失败,将应用 else 子模式值。

我们的 if 条件检查是否存在特定键。 如果密钥存在,则应用引用正确架构的架构。

因为希望条件互斥,所以需要将多个条件包裹在一个oneOf中,并在条件检查中加入else: falsefalse 作为架构使验证失败。

如果您想对以上任何内容进行进一步说明,请告诉我。

演示:https://jsonschema.dev/s/HLniL

{
  "$schema": "http://json-schema.org/draft-07/schema",
  "$id": "http://example.com/baseSchema.json",
  "type": "object",
  "required": [
    "payload"
  ],
  "properties": {
    "payload": {
      "$id": "#/properties/payload",
      "type": "object",
      "oneOf": [
        {
          "if": {
            "required": [
              "user"
            ]
          },
          "then": {
            "$ref": "userSchema.json"
          },
          "else": false
        },
        {
          "if": {
            "required": [
              "users"
            ]
          },
          "then": {
            "$ref": "usersSchema.json"
          },
          "else": false
        }
      ]
    }
  },
  "definitions": {
    "user": {
      "$id": "http://example.com/userSchema.json",
      "type": "object",
      "required": [
        "user"
      ],
      "properties": {
        "user": {
          "$ref": "userProperties.json"
        }
      }
    },
    "users": {
      "$id": "http://example.com/usersSchema.json",
      "type": "object",
      "required": [
        "users"
      ],
      "properties": {
        "users": {
          "type": "array",
          "items": {
            "$ref": "userProperties.json"
          }
        }
      }
    },
    "userProperties": {
      "$id": "http://example.com/userProperties.json",
      "type": "object",
      "properties": {
        "firstName": {
          "type": "string"
        }
      }
    }
  }
}