我有以下 json 模式,我想用它来验证数据。使用
jsonschema
验证基本信息和条件场景时效果很好。
但我有一个具体的问题,我无法根据 allOf 条件轻松评估数据是否存在但不应该存在。可以在 python 中为简单的条件编写一些自定义的东西,但如果条件更复杂,扩展可能会很棘手。有谁有任何提示或知道任何可以提供帮助的工具。非常感谢
示例架构
{
"$schema": "https://json-schema.org/draft/2019-09/schema",
"type": "object",
"properties": {
"colours": {
"type": "integer",
"oneOf": [
{"const": 1},
{"const": 2},
{"const": 3},
{"const": 19}
]
},
"years": {
"type": "integer",
"minimum": 1,
"maximum": 10
},
"sleep": {
"type": "integer",
"oneOf": [
{"const": 1},
{"const": 2},
{"const": 5}
]
},
"shapes": {
"type": "array",
"items": {
"type": "integer",
"anyOf": [
{"const": 2},
{"const": 3}
]
}
},
"gender": {
"type": "integer",
"oneOf": [
{"const": 1},
{"const": 2}
]
}
},
"required": ["colours", "years"],
"allOf": [
{
"if": {
"allOf": [
{
"properties": {
"colours": {"const": 1}
}
},
{
"properties": {
"years": {
"enum": [7,8,9]
}
}
}
]
},
"then": {
"required": ["shapes"]
}
},
{
"if": {
"allOf": [
{
"properties": {
"shapes": {
"anyOf": [
{"const": 1},
{"const": 3}
]
}
}
},
{
"properties": {
"colours": {"const": 19}
}
}
]
},
"then": {
"required": ["gender"]
}
},
{
"if": {
"properties": {
"years": {
"not": {"const": 1}
}
}
},
"then": {
"required": ["sleep"]
}
}
]
}
data_list = [
{"id": "a", "colours": 1, "years": 9, "sleep": 4, "shapes": [1], "gender": 3}, # valid logic but invalid value for sleep
{"id": "b", "colours": 1, "years": 6, "shapes": 3, "gender": 3}, # invalid as sleep should not be present, nor should gender since the entry to shape is incorrect, shapes also not array
{"id": "c", "colours": 1, "years": 9, "sleep": 3}, # invalid as shapes should be present
{"id": "d", "colours": 1, "years": 1, "sleep": 5}, # invalid as sleep is present but shouldnt be
]
from jsonschema import validate, Draft7Validator, ValidationError
for data in data_list:
validator = Draft7Validator(schema)
errors = sorted(validator.iter_errors(data), key=lambda e: e.path)
if errors:
print(data.get("id"))
for error in errors:
print(f"Schema Error in {list(error.path)}: {error.message}")
# not indicating that sleep is not required for id d
您在
oneOf
anyOf
中使用了很多不必要的语法,并且您的条件
if, then
和 allOf
组合可以简化很多。其次,如果要枚举多个条件,最好使用 enum
而不是 oneOf>const
或
anyOf>const
提供的示例具有比您在评论中描述的更多的失败属性。您的一些条件逻辑是冲突的,因此该架构是不合逻辑的。如果你提供所有条件,我可以帮你解决。以简化的 if, then
结构为例。如果您需要有关条件语句的进一步帮助,请告诉我。
{
"$schema": "https://json-schema.org/draft/2019-09/schema",
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"properties": {
"colours": {
"enum": [
1,
2,
3,
19
]
},
"years": {
"type": "integer",
"minimum": 1,
"maximum": 10
},
"sleep": {
"enum": [
1,
2,
5
]
},
"shapes": {
"type": "array",
"items": {
"enum": [
2,
3
]
}
},
"gender": {
"enum": [
1,
2
]
}
},
"required": [
"colours",
"years"
],
"allOf": [
{
"if": {
"required": [
"colours",
"years"
],
"properties": {
"colours": {
"const": 1
},
"years": {
"enum": [
7,
8,
9
]
}
}
},
"then": {
"required": [
"shapes"
],
"not": {
"required": [
"sleep"
]
}
}
},
{
"if": {
"required": [
"shapes",
"colours"
],
"properties": {
"colours": {
"const": 19
},
"shapes": {
"type": "array",
"items": {
"enum": [
1,
3
]
}
}
}
},
"then": {
"required": [
"gender"
]
},
"else": {
"not": {
"required": [
"gender"
]
}
}
},
{
"if": {
"required": [
"years"
],
"properties": {
"years": {
"not": {
"const": 1
}
}
}
},
"then": {
"required": [
"sleep"
]
}
}
]
}
}