如何指定JSON对象应该采用哪一项?

时间:2017-07-24 13:09:20

标签: json jsonschema

使用Python和ObjA我正在尝试验证ObjBbeta等的分配到test.json{ "alpha": { "beta": "ObjA" } }

testschema.json

在我的架构中(betaoneOf a有多个项目,每个项目定义如下(b,{{1}的值不同}和c

"ObjA": {

    "type": "object",
    "properties": {

        "items": {

            "a": [90, 95],
            "b": [4, 8],
            "c": [0.2, 0.6]
        }
    },

    "additionalProperties": false
}

也就是说,beta可以采用oneOfObjAObjBObjC的{​​{1}}值。我只是想在ObjD

中指定它应该使用哪一个
test.json

但是,尝试使用"alpha": { "type": "object", "properties": { "beta": { "oneOf": [ { "type": "object", "properties": { "ObjA": { "type": "object", "properties": { "items": { "a": [90, 95], "b": [4, 8], "c": [0.2, 0.6] } }, "additionalProperties": false } }, "additionalProperties": false }, { "type": "object", "properties": { "ObjB": { "type": "object", "properties": { "items": { "a": [100], "b": [0], "c": [0] } }, "additionalProperties": false } } }, ... ObjC and ObjD defined ... } } } },

验证架构时
jsonschema.validate()

我收到以下错误

### Test the whole JSON is valid against the Schema
def test_valid__JSON_against_schema(self):

    with open(schema_filename) as schema_file:
        test_schema = json.load('testschema.json')
    schema_file.close()

    with open(json_filename) as json_file:
        test_json = json.load('test.json')
    json_file.close()

    validate(test_json, test_schema)

这是整个消息

Failed validating 'oneOf' in schema['properties']['alpha']['properties']['beta']:

使用在线E ====================================================================== ERROR: test_valid__JSON_against_schema (__main__.SchemaTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "test_test-variables.py", line 35, in test_valid__JSON_against_schema validate(test_json, test_schema) File "/local/tools/PACKAGES/python3/lib/python3.6/site-packages/jsonschema/validators.py", line 541, in validate cls(schema, *args, **kwargs).validate(instance) File "/local/tools/PACKAGES/python3/lib/python3.6/site-packages/jsonschema/validators.py", line 130, in validate raise error jsonschema.exceptions.ValidationError: 'ObJA' is not valid under any of the given schemas Failed validating 'oneOf' in schema['properties']['alpha']['properties']['beta']: {'oneOf': [{'additionalProperties': False, 'properties': {'ObjA': {'additionalProperties': False, 'properties': {'items': {'a': [0.2, 0.6], 'b': [90, 95], 'c': [4, 8]}}, 'type': 'object'}}, 'type': 'object'}, {'additionalProperties': False, 'properties': {'ObjB': {'additionalProperties': False, 'properties': {'items': {'a': [0], 'b': [100], 'c': [0]}}, 'type': 'object'}}, 'type': 'object'}, {'additionalProperties': False, 'properties': {'ObjC': {'additionalProperties': False, 'properties': {'items': {'a': [0], 'b': [50], 'c': [50]}}, 'type': 'object'}}, 'type': 'object'}, {'additionalProperties': False, 'properties': {'ObjD': {'additionalProperties': False, 'properties': {'items': {'a': [100], 'b': [0], 'c': [0]}}, 'type': 'object'}}, 'type': 'object'}]} On instance['alpha']['beta']: 'ObjA' ---------------------------------------------------------------------- Ran 1 test in 0.007s FAILED (errors=1) 验证器(http://json-schema-validator.herokuapp.com/jsonschema无法验证,因此我从文件中删除了对test.json的任何提及(即alpha })并且验证器报告了以下内容

{ }

恢复[ { "level" : "warning", "schema" : { "loadingURI" : "#", "pointer" : "/properties/alpha/properties/beta/oneOf/0/properties/ObjA/properties/items" }, "domain" : "syntax", "message" : "the following keywords are unknown and will be ignored: [a, b, c]", "ignored" : [ "a", "b", "c" ] } ] ,验证提供

test.json

有谁知道这样做的正确方法?

感谢。

1 个答案:

答案 0 :(得分:3)

让我们找出失败的架构部分。

{
  "type": "object",
  "properties": {
    "ObjA": {
      "type": "object",
      "properties": {
        "items": {
          "a": [90, 95],
          "b": [4, 8],
          "c": [0.2, 0.6]
        }
      },
      "additionalProperties": false
    }
  },
  "additionalProperties": false
}

这是对这部分测试数据进行评估

"ObjA"

您看到的错误告诉您测试数据是一个字符串,但架构要求它是一个对象。

与您的架构匹配的测试数据看起来像这样

{
  "ObjA": {
    "items": ???
  }
}

我在这里使用???,因为此处的值可以是任何有效JSON的值。原因是因为此架构不包含任何JSON Schema关键字。

{
  "a": [90, 95],
  "b": [4, 8],
  "c": [0.2, 0.6]
}

因此,对它的价值没有限制。您看到的警告消息告诉您abc不是关键字。

我不知道你想用这个模式表达什么,但它与测试数据中的简单字符串相差甚远。

编辑以回应评论

听起来你正试图将JSON Schema用于不适合的东西。模式应该仅描述用户需要关注的内容。您必须在另一个步骤中将用户值映射到硬编码结构。无论如何,听起来你需要enum而不是oneOf

{
  "enum": ["ObjA", "ObjB", "ObjC", "ObjD"]
}

{
  "enum": [
    {
      "a": [90, 95],
      "b": [4, 8],
      "c": [0.2, 0.6]
    },
    {
      "a": [100],
      "b": [0],
      "c": [0]
    },
    ...
  ]
}

没有办法同时拥有两者。如果您确实需要在架构中表达,我会添加一个显示映射的自定义关键字。验证器将忽略它(并且您可能会收到警告),但这种关系将表达给人类读者和自定义工具。它可能看起来像这样

{
  "enum": ["ObjA", "ObjB", "ObjC", "ObjD"]
  "enumValues": {
    "ObjA": {
      "a": [90, 95],
      "b": [4, 8],
      "c": [0.2, 0.6]
    },
    "ObjB": {
      "a": [100],
      "b": [0],
      "c": [0]
    },
    ...
  ]
}

enum告诉用户允许的值是什么,验证器可以检查这个值。然后enumValues关键字是我们用来表达枚举值与其实际值之间关系的结果。