使用JsonSchema和$ ref验证对象的异构列表

时间:2019-03-14 16:59:24

标签: jsonschema python-jsonschema

我看到了类似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"]
    }
  }
}

提前谢谢!

1 个答案:

答案 0 :(得分:2)

让我惊讶的第一件事是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不是{{1 }})。 (实际上,它们被定义为显式令牌。)


您的问题尚不清楚的是False对象是否需要foobaraa参数,而ab对象是否需要barfoo和{{ 1}}参数。在这种情况下,如果您使用的是JSON Schema draft 6或更高版本,则可以做一些其他事情。

草稿6定义了一个ba属性,您可以使用该属性来隔离特定属性的值,并在对象的其他部分上实施子模式。使用此功能,您可以创建一种 switch 语句。

bb

这有点重组,您需要为每个const的值使用一个{ "$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"] } } } } }

此外,如果您使用的是草稿7,那么您也可以使用schema_? / arbitrary_name / if关键字,但我认为这不会使该用例成为现实清洁工。