Python 中 jsonschema 深度运用

开发 前端
jsonschema 是一个强大的库,用于验证 JSON 数据是否符合特定的模式(Schema)。在实际应用中,你可能会遇到更复杂的 JSON 结构和验证需求。下面我将详细介绍 jsonschema 的一些高级用法,包括复杂的数据结构、自定义验证器以及如何处理嵌套的 JSON 对象。

前言

jsonschema 是一个强大的库,用于验证 JSON 数据是否符合特定的模式(Schema)。在实际应用中,你可能会遇到更复杂的 JSON 结构和验证需求。下面我将详细介绍 jsonschema 的一些高级用法,包括复杂的数据结构、自定义验证器以及如何处理嵌套的 JSON 对象。

1. 复杂的数据结构

1.1 数组验证

你可以验证数组中的每个元素是否符合特定的模式。

import json
from jsonschema import validate, ValidationError
# 定义 JSON Schema
schema = {
    "type": "object",
    "properties": {
        "name": {"type": "string"},
        "ages": {
            "type": "array",
            "items": {
                "type": "integer",
                "minimum": 0,
                "maximum": 120
            }
        }
    },
    "required": ["name", "ages"]
}
# 待验证的 JSON 数据
data = {
    "name": "Alice",
    "ages": [25, 30, 35]
}
# 验证 JSON 数据
try:
    validate(instance=data, schema=schema)
    print("JSON data is valid.")
except ValidationError as e:
    print(f"JSON data is invalid: {e}")
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.

1.2 嵌套对象验证

你可以验证嵌套的对象是否符合特定的模式。

# 定义 JSON Schema
schema = {
    "type": "object",
    "properties": {
        "name": {"type": "string"},
        "address": {
            "type": "object",
            "properties": {
                "street": {"type": "string"},
                "city": {"type": "string"},
                "zipcode": {"type": "string"}
            },
            "required": ["street", "city"]
        }
    },
    "required": ["name", "address"]
}
# 待验证的 JSON 数据
data = {
    "name": "Alice",
    "address": {
        "street": "123 Main St",
        "city": "Anytown",
        "zipcode": "12345"
    }
}
# 验证 JSON 数据
try:
    validate(instance=data, schema=schema)
    print("JSON data is valid.")
except ValidationError as e:
    print(f"JSON data is invalid: {e}")
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.

2. 自定义验证器

有时候你需要进行更复杂的验证逻辑,这时可以使用 jsonschema 的 Validator 类来创建自定义验证器。

2.1 自定义格式验证

你可以添加自定义的格式验证器,例如验证电话号码格式。

from jsonschema import Draft7Validator, FormatChecker, ValidationError
# 定义自定义格式验证器
def is_valid_phone_number(phone_number):
    return phone_number.isdigit() and len(phone_number) == 10
format_checker = FormatChecker()
format_checker.checks('phone')(is_valid_phone_number)
# 定义 JSON Schema
schema = {
    "type": "object",
    "properties": {
        "name": {"type": "string"},
        "phone": {"type": "string", "format": "phone"}
    },
    "required": ["name", "phone"]
}
# 待验证的 JSON 数据
data = {
    "name": "Alice",
    "phone": "1234567890"
}
# 创建 Validator 并验证 JSON 数据
validator = Draft7Validator(schema, format_checker=format_checker)
try:
    validator.validate(data)
    print("JSON data is valid.")
except ValidationError as e:
    print(f"JSON data is invalid: {e}")
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.

2.2 自定义验证函数

你可以为特定属性添加自定义的验证逻辑。

from jsonschema import Draft7Validator, ValidationError
# 定义自定义验证函数
def is_even(value):
    if value % 2 != 0:
        raise ValidationError(f"{value} is not an even number")
# 定义 JSON Schema
schema = {
    "type": "object",
    "properties": {
        "name": {"type": "string"},
        "number": {"type": "integer"}
    },
    "required": ["name", "number"],
    "additionalProperties": False
}
# 创建 Validator 并添加自定义验证函数
validator = Draft7Validator(schema)
validator.VALIDATORS["even"] = is_even
schema["properties"]["number"]["even"] = True
# 待验证的 JSON 数据
data = {
    "name": "Alice",
    "number": 4
}
# 验证 JSON 数据
try:
    validator.validate(data)
    print("JSON data is valid.")
except ValidationError as e:
    print(f"JSON data is invalid: {e}")
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.

3. 使用 RefResolver 进行模块化验证

对于大型项目,你可能希望将 Schema 分成多个文件,并使用引用($ref)来组合它们。RefResolver 可以帮助你管理这些引用。

3.1 模块化 Schema 文件

假设你有两个文件:person_schema.json 和 address_schema.json。

person_schema.json
{
    "$id": "http://example.com/schemas/person",
    "type": "object",
    "properties": {
        "name": {"type": "string"},
        "address": {"$ref": "http://example.com/schemas/address"}
    },
    "required": ["name", "address"]
}
address_schema.json
{
    "$id": "http://example.com/schemas/address",
    "type": "object",
    "properties": {
        "street": {"type": "string"},
        "city": {"type": "string"},
        "zipcode": {"type": "string"}
    },
    "required": ["street", "city"]
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.

3.2 使用 RefResolver 进行验证

import json
from jsonschema import RefResolver, Draft7Validator, ValidationError
# 读取 Schema 文件
with open('person_schema.json') as f:
    person_schema = json.load(f)
with open('address_schema.json') as f:
    address_schema = json.load(f)
# 创建 RefResolver
resolver = RefResolver(
    base_uri="http://example.com/schemas/",
    referrer=person_schema,
    store={
        "http://example.com/schemas/person": person_schema,
        "http://example.com/schemas/address": address_schema
    }
)
# 创建 Validator
validator = Draft7Validator(person_schema, resolver=resolver)
# 待验证的 JSON 数据
data = {
    "name": "Alice",
    "address": {
        "street": "123 Main St",
        "city": "Anytown",
        "zipcode": "12345"
    }
}
# 验证 JSON 数据
try:
    validator.validate(data)
    print("JSON data is valid.")
except ValidationError as e:
    print(f"JSON data is invalid: {e}")
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.

4. 使用 jsonschema 进行数据转换

虽然 jsonschema 主要用于验证,但你可以结合其他库(如 voluptuous 或 marshmallow)来进行数据转换和验证。

4.1 结合 voluptuous 进行数据转换

voluptuous 是一个轻量级的数据验证和转换库,可以与 jsonschema 结合使用。

import json
import voluptuous as vol
from jsonschema import validate, ValidationError
# 定义 JSON Schema
schema = {
    "type": "object",
    "properties": {
        "name": {"type": "string"},
        "age": {"type": "integer", "minimum": 0},
        "email": {"type": "string", "format": "email"}
    },
    "required": ["name", "age"]
}
# 定义 Voluptuous Schema
vol_schema = vol.Schema({
    vol.Required('name'): str,
    vol.Required('age'): int,
    vol.Optional('email'): vol.Email()
})
# 待验证的 JSON 数据
data = {
    "name": "Alice",
    "age": 30,
    "email": "alice@example.com"
}
# 验证 JSON 数据
try:
    validate(instance=data, schema=schema)
    transformed_data = vol_schema(data)
    print("JSON data is valid and transformed:", transformed_data)
except (ValidationError, vol.Invalid) as e:
    print(f"JSON data is invalid: {e}")
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
责任编辑:华轩 来源: 测试开发学习交流
相关推荐

2017-08-01 09:37:00

深度学习美团机器学习

2016-12-21 16:40:22

TensorFlow深度学习算法大数据

2023-08-23 07:21:44

JsonSchema测试

2016-10-21 14:57:10

2009-12-30 20:44:04

IT系统管理运维管理摩卡软件

2019-12-23 15:10:10

人脸识别AI人工智能

2011-01-11 10:21:56

TCPIP流量整形

2010-03-10 18:32:45

Python多线程

2013-01-28 10:15:55

MPLS华为路由器

2009-07-30 14:03:04

ASP.NET中的se

2010-11-12 09:18:13

SQL Server存

2021-08-18 16:05:40

鸿蒙HarmonyOS应用

2010-03-15 14:52:02

Python 3.0

2019-06-17 07:59:32

大数据CTOTeradata

2024-05-15 09:05:43

Python文档处理工具自动化文档生成

2023-11-13 22:30:16

C++开发

2021-01-21 05:46:22

JavaLambda开发

2019-03-06 09:55:54

Python 开发编程语言

2011-12-30 13:15:53

Java

2022-02-15 23:38:22

Python机器学习算法
点赞
收藏

51CTO技术栈公众号