【问题标题】:Validating Heterogeneous Lists of Objects with JsonSchema and $ref使用 JsonSchema 和 $ref 验证对象的异构列表
【发布时间】:2019-08-05 16:24:59
【问题描述】:

我已经看到了与 not quite match this particular case 类似的问题的答案,如果我错过了相关答案,我们深表歉意。

我有一个要验证的异构对象数组。这些对象在顶层具有相同的格式,但子对象完全不同,只能通过每个子对象中存在的属性来识别。

问题映射到验证以下数据,尽管我在数组中有两个以上的对象类型:

{
  "heterogeneous_array": [{
      "arbitrary_name": "foobar",
      "params": {
        "aa": "foo",
        "ab": "bar"
      }
    },
    {
      "arbitrary_name": "barfoo",
      "params": {
        "ba": "baz",
        "bb": "bot"
      }
    }
  ]
}

我正在使用以下模式,它声称即使“params”键下的对象无效,也可以验证输入 json。如何修复 json 架构?

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "heterogeneous_array": {
      "$ref": "#/definitions/heterogeneous_array"
    }
  },
  "definitions": {
    "heterogeneous_array": {
      "type": "array",
      "items": {
        "arbitrary_name": {
          "type": "string"
        },
        "params": {
          "oneOf": [{
              "$ref": "#/definitions/schema_a"
            },
            {
              "$ref": "#/definitions/schema_b"
            }
          ]
        },
        "required": ["arbitrary_name", "params"]
      }
    },
    "schema_a": {
      "properties": {
        "aa": {
          "type": "string"
        },
        "ab": {
          "type": "string"
        }
      },
      "additionalProperties": false,
      "required": ["aa", "ab"]
    },
    "schema_b": {
      "properties": {
        "ba": {
          "type": "string"
        },
        "bb": {
          "type": "string"
        }
      },
      "additionalProperties": false,
      "required": ["ba", "bb"]
    }
  }
}

提前谢谢你!

【问题讨论】:

    标签: jsonschema python-jsonschema


    【解决方案1】:

    我首先想到的是 parametersarbitrary_name 不是 JSON Schema 关键字。我认为您缺少一些 properties 关键字。

    试试这个:

    {
      "$schema": "http://json-schema.org/draft-07/schema#",
      "type": "object",
      "properties": {
        "heterogeneous_array": {
          "$ref": "#/definitions/heterogeneous_array"
        }
      },
      "definitions": {
        "heterogeneous_array": {
          "type": "array",
          "items": {
            "properties": {             // missing this
              "arbitrary_name": {
                "type": "string"
              },
              "params": {
                "oneOf": [{
                    "$ref": "#/definitions/schema_a"
                  },
                  {
                    "$ref": "#/definitions/schema_b"
                  }
                ]
              }
            },
            "required": ["arbitrary_name", "params"]    // "arbitrary_name" was "name"
          }
        },
        "schema_a": {
          "properties": {             // was "parameters"
            "aa": {
              "type": "string"
            },
            "ab": {
              "type": "string"
            }
          },
          "additionalProperties": false,
          "required": ["aa", "ab"]
        },
        "schema_b": {
          "properties": {             // was "parameters"
            "ba": {
              "type": "string"
            },
            "bb": {
              "type": "string"
            }
          },
          "additionalProperties": false,
          "required": ["ba", "bb"]
        }
      }
    }
    

    我还评论了一些其他内容。

    最后一件事(修复你所拥有的)是次要的,应该注意,并且无论如何你的 JSON 库可能都支持:JSON 中的布尔值总是小写的(例如 false 而不是 False)。 (它们实际上被定义为显式标记。)


    您的问题不清楚foobar 对象是否需要aaab 参数,而barfoo 对象是否需要babb 参数。如果是这种情况,如果您使用的是 JSON Schema Draft 6 或更高版本,则可以做一些其他事情。

    Draft 6 定义了一个const 属性,您可以使用它来隔离特定属性的值并在对象的其他部分强制执行子模式。使用它,您可以创建一种 switch 语句。

    {
      "$schema": "http://json-schema.org/draft-07/schema#",
      "type": "object",
      "properties": {
        "heterogeneous_array": {
          "$ref": "#/definitions/heterogeneous_array"
        }
      },
      "definitions": {
        "heterogeneous_array": {
          "type": "array",
          "items": {
            "oneOf": [
              {"$ref": "#/definitions/schema_a"},
              {"$ref": "#/definitions/schema_b"}
            ],
            "required": ["arbitrary_name", "params"]
          }
        },
        "schema_a": {
          "properties": {
            "arbitrary_name": {"const": "foobar"},
            "params": {
              "properties": {
                "aa": {
                  "type": "string"
                },
                "ab": {
                  "type": "string"
                }
              },
              "additionalProperties": false,
              "required": ["aa", "ab"]
            }
          }
        },
        "schema_b": {
          "properties": {
            "arbitrary_name": {"const": "barfoo"},
            "params": {
              "properties": {
                "ba": {
                  "type": "string"
                },
                "bb": {
                  "type": "string"
                }
              },
              "additionalProperties": false,
              "required": ["ba", "bb"]
            }
          }
        }
      }
    }
    

    这有点重组,您需要为您拥有的每个 arbitrary_name 值提供一个 schema_?

    除此之外,如果您使用的是草案 7,您还可以使用 if/then/else 关键字,但我认为这不会让这个用例变得更清晰。

    【讨论】:

    • 谢谢!您的 cmets 非常有帮助,我之前没有听说过 const 属性。 False vs false 也是一个不错的选择。奇怪的是,我有一个包含属性标签的版本,但我一定错过了以另一种方式配置它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-09
    • 1970-01-01
    • 2022-01-04
    • 1970-01-01
    • 2018-11-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多