【问题标题】:validating against a JSON schema containing multiple schema definitions针对包含多个模式定义的 JSON 模式进行验证
【发布时间】:2021-06-02 08:11:40
【问题描述】:

我正在创建一个用于 Postman 的 JSON 模式,其中包含一些模式定义。我针对架构验证的 JSON 需要与架构定义之一匹配。

示例架构

{
  "oneOf": [
    {
      "$ref": "#/definitions/schema1"
    },
    {
      "$ref": "#/definitions/schema2"
    },
    {
      "$ref": "#/definitions/schema3"
    }
  ],
  "definitions": {
    "schema1": {
      "type": "object",
      "properties": {
        "propertyA": {
          "type": "string"
        }
      },
      "required": [
        "propertyA"
      ]
    },
    "schema2": {
      "type": "object",
      "properties": {
        "propertyB": {
          "type": "string"
        }
      },
      "required": [
        "propertyB"
      ]
    },
    "schema3": {
      "type": "object",
      "properties": {
        "propertyC": {
          "type": "string"
        }
      },
      "required": [
        "propertyC"
      ]
    }
  }
}

JSON 数据示例

此 JSON 已针对架构进行验证并正确标记为无效(因为需要字符串):

{
    "propertyA": 123
}

问题

本例根据https://www.jsonschemavalidator.net/返回4个错误:

  • 消息:JSON 对来自“oneOf”的无模式有效。架构路径: #/oneOf
  • 消息:类型无效。预期字符串,但得到整数。架构路径: #/definitions/schema1/properties/propertyA/type
  • 消息:对象缺少必需的属性:propertyC。
    架构路径:#/definitions/schema3/required
  • 消息:对象:propertyB 中缺少必需的属性。
    架构路径:#/definitions/schema2/required

我只对说它需要一个字符串的错误消息感兴趣。 如何在将架构定义保存在 1 个文件中的同时避免其他错误消息?

【问题讨论】:

  • 想象你有一个类似 oneof string, number 但 gut null 的模式。您希望验证抛出哪个错误?它的逻辑相同,验证不知道你对哪一个感兴趣,因为一切都是无效的
  • @PDHide 我从您的评论中了解到,验证不知道要针对哪个架构进行验证,因此要针对所有架构进行验证。所以我想真正的问题是,如何避免这种情况。 Jason Desrosiers 的回答似乎很有希望解决这个问题。
  • 是的,答案真的很好

标签: json postman jsonschema


【解决方案1】:

是的,oneOf 对这种事情很糟糕。 if/then 很冗长,但会给您带来更好的结果。基本上,您需要确定一些条件来确定架构是否应应用于实例。

通常,该条件是公共字段的值。在这种情况下,如果要验证的实例是具有"type": "A" 的对象,那么它必须针对/definitions/a 模式进行验证。如果它有"type": "B",那么它必须针对/definitions/b 模式进行验证。

{
  "allOf": [
    {
      "if": {
        "properties": {
          "type": { "const": "A" }
        },
        "required": ["type"]
      },
      "then": { "$ref": "#/definitions/a" }
    },
    {
      "if": {
        "properties": {
          "type": { "const": "B" }
        },
        "required": ["type"]
      },
      "then": { "$ref": "#/definitions/b" }
    }
  ]
}

如果您的条件是存在特定字段,您可以使用dependencies 关键字作为快捷方式。如果正在验证的实例是具有“propertyA”属性的对象,则该实例必须对/definitions/a 模式有效。对于“propertyB”也是如此。

{
  "dependencies": {
    "propertyA": { "$ref": "#/definitions/a" },
    "propertyB": { "$ref": "#/definitions/b" }
  }
}

您的示例实际上有一个超级简单的解决方案,但我回答的是一般情况,因为我假设您的实际架构比示例更复杂。

{
  "type": "object",
  "properties": {
    "propertyA": { "type": "string" },
    "propertyB": { "type": "string" },
    "propertyC": { "type": "string" }
  },
  "oneOf": [
    { "required": ["propertyA"] },
    { "required": ["propertyB"] },
    { "required": ["propertyC"] }
  ]
}

【讨论】:

  • 很好的答案杰森 :-)。你猜对了,我的真实模式要复杂一些。我可能过于简化了我的例子。在确定需要验证的架构之前,我需要识别多个字段。我认为 if/then 关键字确实是我需要的。如果成功,我会尝试并标记您的答案。
猜你喜欢
  • 2010-11-08
  • 2021-06-16
  • 2023-03-08
  • 2015-06-07
  • 2010-12-07
  • 1970-01-01
  • 2017-01-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多