在上一节“Python小酷库系列:Python中的JSON工具库(1)”中,我们介绍了“普通玩家”和“高性能玩家”常用的JSON工具库,本节我们将拓宽视野,从功能性的角度介绍一些Python中的JSON工具库。
复杂数据类型转换
1、json5
json5 是 JSON 的超集,允许更宽松的语法(如允许注释、单引号、不加引号的键等),适合人类书写配置文件。json5 库提供了对 JSON5 格式的解析支持。
安装
pip install json5
基本使用
import json5
# JSON5 字符串,包含注释、单引号、不加引号的键等
json5_str = """
{
// 这是一个注释
unquotedKey: 'value',
"quotedKey": 123,
trailingComma: true,
}
"""
# 解析 JSON5 字符串
data = json5.loads(json5_str)
print(data)
# 输出: {'unquotedKey': 'value', 'quotedKey': 123, 'trailingComma': True}
json5 库支持的扩展语法解析:
| 特性 | 说明 |
|---|---|
| 注释 | 支持 // 单行注释 和 /* */ 多行注释 |
| 尾逗号 | 允许最后一个元素后写逗号 |
| 单引号字符串 | ‘text’ 与 “text” 都合法 |
| 未加引号的键 | 允许键名不加引号(如 foo: 1) |
| 十六进制数字 | 支持 0x1234 数字表示 |
| 正负号数字 | 支持 +1、-2 |
| 多行字符串 | 可以使用 \ 跨行字符串 |
| 数字中的下划线 | 如 1_000_000(提高可读性) |
写入 JSON5 数据
虽然 json5 支持读取 JSON5 文件,但并不支持将 Python 对象序列化为 JSON5 格式(即没有 json5.dumps() 带有 JSON5 特性的输出功能)。它只能写成标准 JSON:
data = {'foo': 'bar'}
print(json5.dumps(data)) # 输出: {"foo": "bar"}
2、dataclasses_json
dataclasses-json主要用于dataclasses 的 JSON 序列化/反序列化,它还支持dataclasses与dict类型的互相转化, 是 dataclasses 的一个强力补丁库。
安装
pip install dataclasses-json
基本使用
from dataclasses import dataclass
from dataclasses_json import dataclass_json
@dataclass_json
@dataclass
class User:
id: int
name: str
user = User(id=1, name='Alice')
# 序列化为 JSON 字符串
json_str = user.to_json()
print(json_str) # {"id": 1, "name": "Alice"}
# 反序列化为 Python 对象
new_user = User.from_json('{"id": 2, "name": "Bob"}')
print(new_user.name) # Bob
# 转为字典
print(user.to_dict()) # {'id': 1, 'name': 'Alice'}
# 从字典创建
u = User.from_dict({'id': 3, 'name': 'Carol'})
print(u)
嵌套结构支持
@dataclass_json
@dataclass
class Address:
city: str
zipcode: str
@dataclass_json
@dataclass
class Person:
name: str
address: Address
p = Person(name='Tom', address=Address(city='NY', zipcode='10001'))
print(p.to_json())
# {"name": "Tom", "address": {"city": "NY", "zipcode": "10001"}}
# 自动反序列化嵌套结构
data = Person.from_json('{"name": "Amy", "address": {"city": "LA", "zipcode": "90001"}}')
print(data.address.city) # LA
转换配置
config函数可以用于配置字段的类型和别名等。
@dataclass_json
@dataclass
class Data:
user_id: int = config(field_name='userId')
time: datetime = config(
encoder=datetime.isoformat,
decoder=datetime.fromisoformat,
mm_field=fields.DateTime()
)
d = Data(user_id=1001, time=datetime(2024, 1, 1, 12, 0))
print(d.to_json()) # {"userId": 1001,"time":"2024-01-01T12:00:00"}
JSON数据校验
1、jsonschema
jsonschema 是 Python 中用于JSON 数据结构验证的官方实现之一,遵循 JSON Schema 标准,可以验证 JSON 数据是否符合你定义的“规则/结构”。
安装
pip install jsonschema
基本使用
from jsonschema import validate
from jsonschema.exceptions import ValidationError
# 定义 JSON Schema(结构规则)
schema = {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer", "minimum": 0},
},
"required": ["name", "age"]
}
# 要校验的 JSON 数据
data = {
"name": "Alice",
"age": 30
}
try:
validate({"name": "Bob"}, schema)
except ValidationError as e:
print("校验失败:", e.message)
常见规则示例
{
"type": "object",
"properties": {
"username": {"type": "string", "minLength": 3, "pattern": "^[a-zA-Z0-9_]+$"},
"age": {"type": "integer", "minimum": 0, "maximum": 120},
"email": {"type": "string", "format": "email"},
"tags": {
"type": "array",
"items": {"type": "string"},
"maxItems": 5
},
"active": {"type": "boolean"}
},
"required": ["username", "email"]
}
**自定义规则 **
from jsonschema import Draft7Validator, FormatChecker
schema = {
"type": "object",
"properties": {
"phone": {"type": "string", "format": "phone"}
}
}
# 添加自定义格式检查器
@FormatChecker.cls_checks("phone")
def is_phone(value):
import re
return bool(re.match(r'^\d{11}$', value))
data = {"phone": "13800138000"}
validate(data, schema, format_checker=FormatChecker())
数组验证
schema = {
"type": "array",
"items": {"type": "number"},
"minItems": 1,
"uniqueItems": True
}
validate([1, 2, 3], schema) # 正确
validate([], schema) # 失败,元素太少
2、pydantic
Pydantic 是 Python 中最流行的数据验证和数据模型库,它的功能完全有必要另开一篇文章来详细讨论,这里仅仅介绍一下它在JSON 数据校验中的使用。
安装
pip install pydantic
基本使用
from pydantic import Field
class Product(BaseModel):
name: str = Field(..., min_length=3)
price: float = Field(..., gt=0, lt=10000)
# 自动校验 JSON 字段
try:
Product.model_validate({"name": "P", "price": -10})
except ValidationError as e:
print(e)
数组与复杂结构
from typing import List
class Tag(BaseModel):
name: str
class Post(BaseModel):
title: str
tags: List[Tag]
post_data = {
"title": "My Post",
"tags": [{"name": "Python"}, {"name": "FastAPI"}]
}
post = Post.model_validate(post_data)
print(post.tags[0].name) # Python
自定义校验器
from pydantic import field_validator
class User(BaseModel):
username: str
@field_validator('username')
def no_spaces(cls, v):
if ' ' in v:
raise ValueError("username can't contain spaces")
return v
3、Voluptuous
Voluptuous 是一个用于 Python 数据校验的库,语法灵活、结构清晰,不同于jsonschema 所遵循JSON Schema 标准,它采用的是「函数式」「声明式」风格。
安装
pip install voluptuous
基本使用
from voluptuous import Schema, Required, All, Length, Range,MultipleInvalid
schema = Schema({
Required('name'): All(str, Length(min=2)),
Required('age'): All(int, Range(min=0, max=120)),
'email': str,
})
data = {
'name': 'Alice',
'age': 30,
'email': 'alice@example.com'
}
try:
schema({'name': 'A', 'age': -1})
except MultipleInvalid as e:
print("校验失败:", e)
常用的构造器和校验器主要有:
| 校验器 | 功能 |
|---|---|
| Required(…) | 必须字段 |
| Optional(…) | 可选字段 |
| All(…) | 多重条件组合校验器 |
| Length(min, max) | 字符串或列表长度限制 |
| Range(min, max) | 数值范围限制 |
| Match(r’^\w+$') | 正则匹配 |
| In([…]) | 枚举(值必须属于其中之一) |
| Any(A, B) | 多个类型之一 |
| [type] | 列表中每一项的类型 |
| {str: int} | 键值类型均为特定类型的 dict |
嵌套结构与数组校验
config_schema = Schema({
Required('host'): str,
Required('port'): All(int, Range(min=1024, max=65535)),
'debug': bool,
'users': [{
Required('name'): str,
'email': str
}]
})
config = {
'host': 'localhost',
'port': 8000,
'debug': True,
'users': [{'name': 'admin', 'email': 'admin@example.com'}]
}
print(config_schema(config))
自定义验证规则
from voluptuous import Invalid
def is_even(v):
if v % 2 != 0:
raise Invalid("必须为偶数")
return v
schema = Schema({'number': is_even})
print(schema({'number': 4}))
# print(schema({'number': 5})) # 报错
903

被折叠的 条评论
为什么被折叠?



