如何跟踪jsonschema中使用的引用

时间:2019-03-07 20:55:33

标签: json validation python-3.6 jsonschema ref

TLDR:您如何确定在使用jsonschema进行验证期间正在使用哪个引用?

使用:

  • Python 3.6.3
  • jsonschema 2.6.0

我已经定义了使用两个引用级别的架构。在每个级别上,都可以遵循多个参考进行验证。如何确定使用哪个引用来验证提供的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()

0 个答案:

没有答案