无法在一个dict中验证IP地址,文件API.json如下:
{
"$schema": "http://json-schema.org/draft-03/schema#",
"title": "test",
"type": "object",
"properties": {
"type": {"enum": ["spice", "vnc"]},
"listen": {
"type": "string",
"oneOf": [
{"format": "ipv4"},
{"format": "ipv6"}
]
}
},
"additionalProperties": false
}
代码如下:
from jsonschema import Draft3Validator, ValidationError, FormatChecker
import json
if __name__ == '__main__':
graphics1 = {'type': 'spice', 'listen': '0.0.0.0'}
graphics2 = {'type': 'vnc', 'listen': '0.0.0.0'}
graphics3 = {'type': 'abc', 'listen': '0.0.0.0'}
graphics4 = {'type': 'vnc', 'listen': '777.485.999'}
graphics5 = {'type': 'vnc', 'listen': 'fe00::0'}
graphics6 = {'type': 'vnc', 'listen': 'def'}
graphics7 = {'type': 'vnc', 'listen': 'fe00::0abcdefdefs'}
s = json.load(open('API.json'))
validator = Draft3Validator(s, format_checker=FormatChecker())
for x in range(1, 8):
try:
graphics = locals().get('graphics'+str(x))
validator.validate(graphics)
except ValidationError:
print('; '.join(e.message for e in validator.iter_errors(graphics)))
印刷品是这些:
'abc' is not one of [u'spice', u'vnc']
显然,'777.485.999','def'和'fe00 :: 0abcdefdefs'不是ip地址,但测试脚本不会发出警告。 我找到了一个文档(http://tools.ietf.org/html/draft-zyp-json-schema-03),它说的是'ip-address',但不是'ipv4',但它也不起作用。
[编辑]: 我已经为Draft3Validator添加了FormatChecker(),但它仍然无效。但是当我尝试时,Draft4Validator还可以。在doc中,我没有发现Draft3Valdator在任何地方都不支持format / ip-address,它应该可以工作。
答案 0 :(得分:4)
知道了,这不是因为Draft3Validator不支持“format / ip-address”,而是“oneOf”,“allOf”,“anyOf”和“not”。所以API.json应该是:
{
"$schema": "http://json-schema.org/draft-03/schema#",
"title": "test",
"type": "object",
"properties": {
"type": {"enum": ["spice", "vnc"]},
"listen": {
"type": "string",
"format": "ip-address"
}
},
"additionalProperties": false
}
请参阅http://json-schema.org/draft-03/schema#和http://json-schema.org/draft-04/schema#
答案 1 :(得分:3)
查看docs
格式验证是可选的,您需要格式检查才能启用它。
答案 2 :(得分:0)
如果您使用草稿4(http://json-schema.org/draft-04/schema#),我注意到的另一件事是它想要
"format": "ip-address"
进行验证(如果您提供)
"format": "ipv4"
..它根本无法验证。
答案 3 :(得分:0)
document中提到了使用格式检查器的正确方法。[朱利安(Julian)已经提到过]
from jsonschema import Draft3Validator, ValidationError, draft3_format_checker
my_schema = {
"$schema": "http://json-schema.org/draft-03/schema#",
"title": "test",
"type": "object",
"properties": {
"listen": {
"type": "string",
"format": 'ip-address'
},
"type": {"enum": ["spice", "vnc"]}
},
"additionalProperties": False
}
if __name__ == '__main__':
graphics1 = {'type': 'spice', 'listen': 'def'}
graphics2 = {'type': 'vnc', 'listen': '127.0.0.1'}
validator = Draft3Validator(my_schema, format_checker=draft3_format_checker)
for x in range(1, 3):
try:
graphics = locals().get('graphics'+str(x))
validator.validate(graphics)
except ValidationError:
print('; '.join(e.message for e in validator.iter_errors(graphics)))
输出:
'def' is not a 'ip-address'
接下来,当您使用format
时,您可以只使用format
关键字,而没有type
关键字。来源请看此doc的doc和format部分的示例,
my_schema = {
"$schema": "http://json-schema.org/draft-03/schema#",
"title": "test",
"type": "object",
"properties": {
"listen": {
"format": 'ip-address'
},
"type": {"enum": ["spice", "vnc"]}
},
"additionalProperties": False
}
从您的问题来看,您似乎正在尝试同时检查IPv4和IPv6,但如果使用模式format: 'ip-address
,则仅IPv4会得到验证。
from jsonschema import Draft3Validator, ValidationError, draft3_format_checker
my_schema = {
"$schema": "http://json-schema.org/draft-03/schema#",
"title": "test",
"type": "object",
"properties": {
"listen": {
"format": 'ip-address'
},
"type": {"enum": ["spice", "vnc"]}
},
"additionalProperties": False
}
if __name__ == '__main__':
graphics1 = {'type': 'spice', 'listen': 'def'}
graphics2 = {'type': 'vnc', 'listen': '127.0.0.1'}
graphics3 = {'type': 'vnc', 'listen': '::1'} # IPV6 localhost
validator = Draft3Validator(my_schema, format_checker=draft3_format_checker)
for x in range(1, 4):
try:
graphics = locals().get('graphics'+str(x))
validator.validate(graphics)
except ValidationError:
print('; '.join(e.message for e in validator.iter_errors(graphics)))
输出:
'def' is not a 'ip-address'
'::1' is not a 'ip-address'
现在,如果您想同时使用Draft7检查IPv4和IPv6(由于问题很旧,而Draft7的新问题也有很多其他选择)。这是修改后的代码,可同时处理IPv4 / v6错误。
from jsonschema import draft7_format_checker, Draft7Validator
my_schema = {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "test",
"type": "object",
"properties": {
"listen": {
'oneOf': [
{"format": 'ipv4'},
{"format": 'ipv6'},
],
},
"type": {"enum": ["spice", "vnc"]}
},
"additionalProperties": False
}
if __name__ == '__main__':
test_list = [{'type': 'spice', 'listen': 'def'}, {'type': 'vnc', 'listen': '127.0.0.1'},{'type': 'vnc', 'listen': '::1'}]
validator = Draft7Validator(my_schema, format_checker=draft7_format_checker)
for my_json in test_list:
errors = validator.iter_errors(my_json)
for i, error in enumerate(errors):
print(error.message)
# # If you want to see more detail cause of each error use this
# # the ValidationError.context attribute can be used to see the sub-errors which caused the failure
# for i, error in enumerate(errors):
# for suberror in sorted(error.context, key=lambda e: e.schema_path):
# print(list(suberror.relative_schema_path), suberror.message, sep=", ")
输出:
'def' is not valid under any of the given schemas
和详细输出的样本输出(在上面的代码段中已注释)
[0, 'format'], 'def' is not a 'ipv4'
[1, 'format'], 'def' is not a 'ipv6'
error.context
:如果错误是由子方案中的错误引起的,则该属性中将提供子方案中的错误列表。这些错误的schema_path和路径将相对于父错误。
参考:https://python-jsonschema.readthedocs.io/en/stable/errors/