2

我正在尝试json使用 Python 验证有效负载jsonschema 3.0.1,大致看起来像这样(简化为麻烦的部分):

{
    "request": {
        "topic": {
            "param1": "bleep beep topic",
            "param2": "bloop boop topic"
        },
        "message": {
            "param1": "bleep beep message",
            "param2": "bloop boop message"
        }
    }
}

一个有效的请求应该有两个字段:topic和 matching message

它们中的每一个都可以param1仅由一个或两个 param1组成,并且param2

  • 有效的:topic { param1, param2 }, body { param1, param2 }
  • 有效的:topic { param1 }, body { param1 }

但它不能既没有topicwith onlyparam1也有 body with both,也不能有 a topicwith both 和 body with onlyparam2

  • 无效的:topic { param1, param2 }, body { param1 }
  • 无效的:topic { param1}, body { param1, param2 }

因为一个节点的内容取决于另一个节点的内容,所以我无法使用dependencies关键字或if-then-else构造,所以我尝试使用, 并提供一个有效子模式列表,其中包含对和版本的oneOf引用字段,如下所示:one_paramboth_params

from jsonschema import validate

one_param = {
    "type": "object",
    "properties": {
        "param1": {
            "type": "string",
        }
    },
    "required": ["param1"]
}

both_params = {
    "type": "object",
    "properties": {
        "param1": {
            "type": "string",
        },
        "param2": {
            "type": "string",
        }
    },
    "required": ["param1", "param2"]
}

test_schema = {
    "type": "object",
    "properties": {
        "request": {
            "oneOf": [
                {
                    "type": "object",
                    "properties": {
                        "topic": one_param,
                        "message": one_param
                    },

                    "required": ["topic", "message"]
                },
                {
                    "type": "object",
                    "properties": {
                        "topic": both_params,
                        "message": both_params
                    },

                    "required": ["topic", "message"]
                }
            ],
        }
    }
}

验证器的行为不是我所期望的:它在两个参数的情况下都失败了,并成功地验证了一个参数或不匹配的参数的情况。

为什么我的验证模式不能像我解释的那样工作?


这是我为此目的编写的整个测试:

  • good_1案例验证失败
  • good_2,bad_1bad_2成功验证案例
from jsonschema import validate

one_param = {
    "type": "object",
    "properties": {
        "param1": {
            "type": "string",
        }
    },
    "required": ["param1"]
}

both_params = {
    "type": "object",
    "properties": {
        "param1": {
            "type": "string",
        },
        "param2": {
            "type": "string",
        }
    },
    "required": ["param1", "param2"]
}

test_schema = {
    "type": "object",
    "properties": {
        "request": {
            "oneOf": [
                {
                    "type": "object",
                    "properties": {
                        "topic": one_param,
                        "message": one_param
                    },
                    "required": ["topic", "message"]
                },
                {
                    "type": "object",
                    "properties": {
                        "topic": both_params,
                        "message": both_params
                    },
                    "required": ["topic", "message"]
                }
            ],
        }
    }
}

good_1 = {
    "request": {
        "topic": {
            "param1": "bleep beep",
            "param2": "bloop boop"
        },
        "message": {
            "param1": "bleep beep message",
            "param2": "bloop boop message"
        }
    }
}

good_2 = {
    "request": {
        "topic": {
            "param1": "bleep beep"
        },
        "message": {
            "param1": "bleep beep message"
        }
    }
}

bad_1 = {
    "request": {
        "topic": {
            "param1": "bleep beep",
        },
        "message": {
            "param1": "bleep beep message",
            "param2": "bloop boop message with no matching topic"
        }
    }
}

bad_2 = {
    "request": {
        "topic": {
            "param1": "bleep beep",
            "param2": "bloop boop topic with no matching message"
        },
        "message": {
            "param1": "bleep beep message"
        }
    }
}

validate(good_1, test_schema)  # should validate
validate(good_2, test_schema)  # should validate
validate(bad_1, test_schema)  # should fail
validate(bad_2, test_schema)  # should fail
4

1 回答 1

1

使用oneOf,数组中的每个项目(子模式)都应用于数据。如果您测试 中的每个单独的子模式oneOf,会发生什么?

你会发现两者都是有效的!

您的"one_param"架构需要确保包含param2会导致它失败。你可以additionalProperties用来做这个...

{
  "type": "object",
  "properties": {
    "param1": {
      "type": "string"
    }
  },
  "required": [
    "param1"
  ],
  "additionalProperties": false
}

我认为您假设只properties允许定义 in 的属性,但事实并非如此,因此您还需要在required.

您可以通过尝试https://jsonschema.dev上的架构来查看此功能。我已经使用更新的架构和实例预加载了链接。

顺便说一句,如果您希望将架构保存到单个 json 文件中,您可以使用definitions并避免重复子架构。$ref

于 2019-08-12T14:59:11.610 回答