0

我已经看到了与此特定情况不完全匹配的类似问题的答案,因此如果我错过了相关答案,我们深表歉意。

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

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

{
  "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"]
    }
  }
}

先感谢您!

4

1 回答 1

3

我首先想到的是它parameters不是arbitrary_nameJSON 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 中的布尔值总是小写的(例如falsenot False)。(它们实际上被定义为显式标记。)


您的问题不清楚的是foobar对象是否需要aaandab参数,而barfoo对象是否需要baandbb参数。如果是这种情况,如果您使用 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"]
        }
      }
    }
  }
}

这是一个重组,你需要一个你拥有schema_?的每个值arbitrary_name

此外,如果您使用的是 Draft 7,那么您也有if//关键字thenelse但我认为这不会让这个用例变得更清晰。

于 2019-03-14T19:45:35.580 回答