TLDR:您如何确定在使用jsonschema进行验证期间正在使用哪个引用?
使用:
我已经定义了使用两个引用级别的架构。在每个级别上,都可以遵循多个参考进行验证。如何确定使用哪个引用来验证提供的json?断言在验证期间使用了正确的引用时,单元测试将是什么样?以下示例/代码中可能存在一些错误,抱歉,我无法复制/粘贴示例。
我曾考虑过要提高jsonschema模块的日志记录级别,但是在源代码中没有看到任何日志记录对象。
为简洁起见,将示例从原始文档中剥离下来。
message.schema
{
"type":"object",
"properties": {
"messagetype": {
"type": "object",
"oneOf": [
{ "$ref": "request.schema" },
{ "$ref": "response.schema" }
]
}
},
"required": [ "messagetype" ],
"additionalProperties": false
}
request.schema
{
"type": "object",
"properties": {
"request": {
"type": "object",
"oneOf": [
{
"properties": {
"name": { "const": "food" },
"info": { "$ref": "food.schema" }
}
},{
"properties": {
"name": { "const": "shelter" },
"info": { "$ref": "shelter.schema" }
}
}
]
},
"required": [ "name", "info" ],
"additionalProperties": false
},
"required": [ "requesttype" ],
"additionalProperties": false
}
response.schema
{
"type": "object",
"properties": {
"response": {
"type": "object",
"oneOf": [
{
"properties": {
"name": { "const": "meal" },
"info": { "$ref": "meal.schema" }
}
},{
"properties": {
"name": { "const": "house" },
"info": { "$ref": "house.schema" }
}
}
]
},
"required": [ "name", "info" ],
"additionalProperties": false
},
"required": [ "requesttype" ],
"additionalProperties": false
}
food.schema
{
"type": "object",
"properties": {
"nomnoms": {
"type": "string"
}
},
"required": [ "example" ],
"additionalProperties": false
}
shelter.schema
{
"type": "object",
"properties": {
"material": {
"type": "string"
}
},
"required": [ "material" ],
"additionalProperties": false
}
meal.schema
{
"type": "object",
"properties": {
"contains": {
"type": "string"
}
},
"required": [ "contains" ],
"additionalProperties": false
}
house.schema
{
"type": "object",
"properties": {
"rooms": {
"type": "string"
}
},
"required": [ "rooms" ],
"additionalProperties": false
}
request_food_example.json
{
"messagetype": {
"request": {
"name": "food",
"info": {
"nomnoms": "please give me a meal."
}
}
}
}
request_shelter_example.json
{
"messagetype": {
"request": {
"name": "shelter",
"info": {
"material": "brick"
}
}
}
}
response_meal_example.json
{
"messagetype": {
"response": {
"name": "meal",
"info": {
"contains": "all the vitamins and nutrients you need."
}
}
}
}
response_house_example.json
{
"messagetype": {
"response": {
"name": "house",
"info": {
"rooms": "3"
}
}
}
}
schema_validation.py
import json, jsonschema, argparse
from pathlib import Path
class JsonValidator(object):
def __init__(self, schemafileinput, examplefileinput):
self.schemafile = Path(schemafileinput).absolute()
self.jsonfile = Path(examplefileinput).absolute()
if not self.schemafile.exists() or not self.schemafile.is_file():
raise ValueError("Bad schema file [{}]".format(self.schemafile))
if not self.jsonfile.exists() or not self.jsonfile.is_file():
raise ValueError("Bad example file [{}]".format(self.jsonfile))
def validate(self):
with open(schema) as f:
schemadata = f.read()
with open(jsonfile) as f:
exampledata = f.read()
schema = json.loads(schemadata)
example = json.loads(exampledata)
schemafile_directory = "{}/".format(self.schemafile.parent)
resolver = jsonschema.RefResolver("file://" + schemafile_directory, schema)
validator = jsonschema.validators.Draft4Validator(schema, resolver=resolver)
try:
validator.validate(example)
print("Example json is valid")
except Exception:
errors = str()
for error in validator.iter_errors(example):
errors = "{}\n----------next error--------{}".format(errors, error)
raise RuntimeException("Validation failed.\n{}".format(errors))
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("jsonfile")
parser.add_argument("schemafile")
args = parser.parse_args()
validator = JsonValidator(args.jsonfile, args.schemafile)
validator.validate()