一、什么是 JSONSchema?
JSONSchema 是 JSON 数据的「规则说明书 + 校验器」
我们做接口自动化时,接口返回 JSON 格式数据,经常要校验:
- 返回字段有没有缺失(比如少了 code、data)
- 字段数据类型是否正确(code 是字符串、id 是数字,不能返回布尔 / 空)
- 字符串长度、数字范围、数组元素格式是否合规
**总结:**JSONSchema作用:
提前定义 JSON 规范,用代码校验返回数据
来确定数据是否符合约定格式,广泛用于接口自动化测试、前后端联调参数校验。
1.1 安装依赖(固定版本避免报错)
# 统一版本4.23.0,防止新版本API变动
pip install jsonschema==4.23.0
安装成功后即可在 Python 代码导入校验函数。
二、JSONSchema 核心关键字
JSONSchema 本身是一个 JSON 字典结构,通过固定关键字约束数据
下面逐个拆解高频关键字:
2.1 type:限定字段数据类型
type 支持 7 种原生 JSON 类型,对应关系:
| type 取值 | 含义 | 示例数据 |
|---|---|---|
| string | 字符串 | "SUCCESS"、"123" |
| integer | 纯整数 | 10、99(不能带小数) |
| number | 数字 (整数 + 浮点) | 20、3.14 |
| boolean | 布尔 | true/false |
| object | JSON 对象({} 包裹) | {"name":"张三"} |
| array | JSON 数组(\[\] 包裹) | [1,2,3] |
| null | 空值 | null |
示例代码:基础对象类型校验
python
from jsonschema.validators import validate
# 1. 定义校验规则schema(规则说明书)
schema = {
"type": "object", # 根节点整体必须是对象{}
"properties": { # 定义对象里面所有字段的规则
"username": {"type": "string"}, # username必须是字符串
"age": {"type": "integer"} # age必须是整数
}
}
# 2. 待校验的JSON数据(接口返回数据)
right_data = {"username": "小明", "age": 18}
wrong_data = {"username": 123, "age": "十八"} # 类型全错
# 3. 执行校验,符合规则无报错,不符合直接抛异常
validate(instance=right_data, schema=schema)
# validate(instance=wrong_data, schema=schema) # 打开此行会触发校验失败报错
json转JSONSchema太麻烦?使⽤现有⼯具⾃动转换:json转jsonschema工具
注意:⼯具不是万能的,结果可能存在错误。
工具遇到安全问题无法访问需要无视警告继续访问
2.2 required:必填字段约束
required是列表格式,填写字段名,代表这些字段必须存在,缺字段直接校验失败。
python
schema = {
"type": "object",
"required": ["code", "errMsg", "data"], # code、errMsg、data三个字段缺一不可
"properties": {
"code": {"type": "string"},
"errMsg": {"type": "string"},
"data": {"type": ["array", "null"]} # data可以是数组或者null空值
}
}
# 缺了data字段,校验报错
err_json = {"code": "SUCCESS", "errMsg": ""}
# validate(instance=err_json, schema=schema)
2.3 properties:对象字段规则配置
properties用来逐个定义对象内每个字段的校验规则,只约束类型,不代表字段必填(必填要配合 required)。
2.4 数字约束:minimum/maximum(数值范围)
针对integer/number类型,限定数字最大、最小值:
minimum:大于等于该值exclusiveMinimum:严格大于(不能等于)maximum:小于等于该值exclusiveMaximum:严格小于
python
schema = {
"type": "object",
"properties": {
"age": {
"type": "integer",
"minimum": 0, # 年龄≥0
"maximum": 120 # 年龄≤120
}
}
}
2.5 字符串约束:pattern 正则匹配
pattern通过正则表达式约束字符串格式(手机号、邮箱、账号格式校验必备)
python
schema = {
"type": "object",
"properties": {
"phone": {
"type": "string",
"pattern": "^1[3-9]\\d{9}$" # 国内11位手机号正则
}
}
}
2.6 数组约束:items/minItems/maxItems/uniqueItems
数组array专属关键字:
items:约束数组里每一个元素的格式minItems/maxItems:数组最少 / 最多有几个元素uniqueItems: true:数组内元素不能重复
python
schema = {
"type": "object",
"properties": {
"tag_list": {
"type": "array",
"minItems": 1, # 数组最少1个元素
"maxItems":5, # 最多5个元素
"uniqueItems":True,# 元素不能重复
"items": {"type":"string"} # 数组里每个元素必须是字符串
}
}
}
2.7 对象进阶:additionalProperties 禁止多余字段
默认 JSON 对象可以随便加额外字段,additionalProperties:false 表示不允许出现 properties 没定义的字段(严格接口返回校验)
python
schema = {
"type": "object",
"additionalProperties": False, # 不能出现name、age以外的字段
"properties": {
"name": {"type":"string"},
"age": {"type":"integer"}
}
}
# 多了sex字段,校验失败
extra_data = {"name":"小红","age":20,"sex":"女"}
# validate(instance=extra_data,schema=schema)
2.8 对象进阶:min/maxProperties 限制 JSON 键值对数量
minProperties:限制 JSON 对象最少拥有的键值对(属性)数量
实际属性数 < 设定值 → 校验失败
maxProperties:限制 JSON 对象最多拥有的键值对(属性)数量
实际属性数 > 设定值 → 校验失败
作用于
type:object类型;与required(必填字段)是两套规则:
required:管控必须存在哪些 keymin/maxProperties:管控key 总个数范围
python
from jsonschema import validate
# 1、JSON Schema规则:单个博客对象,属性数量必须在7~9个之间
blog_schema = {
"type": "object",
"minProperties": 7, # 最少7个字段
"maxProperties": 9, # 最多9个字段
"properties": {
"id": {"type": "number"},
"title": {"type": "string"},
"content": {"type": "string"},
"userId": {"type": "number"},
"deleteFlag": {"type": "number"},
"createTime": {"type": "string"},
"updateTime": {"type": "string"},
"loginUser": {"type": "boolean"}
}
}
# 样例1:正常数据(一共8个字段,7≤8≤9,校验通过)
normal_data = {
"id": 5,
"title": "自动化测试创建",
"content": "##在这里写下一篇博客",
"userId": 4,
"deleteFlag": 0,
"createTime": "2026-05-23 23:35",
"updateTime": "2026-05-23T15:35:01.000+00:00",
"loginUser": False
}
# 样例2:字段只有5个 < minProperties=7,校验报错
less_data = {
"id": 5,
"title": "自动化测试创建",
"content": "##在这里写下一篇博客",
"userId": 4,
"deleteFlag": 0
}
# 执行校验
validate(instance=normal_data, schema=blog_schema)
print("✅ 正常数据校验通过")
# validate(instance=less_data, schema=blog_schema) #放开此行会抛出:属性数量不足异常
2.9 dependentRequired 设置 "属性依赖" :
设置 "属性依赖" 规则: 如果 A 属性出现了,那么 B 属性 必须也出现,否则校验不通过。
比如:creditCard(信用卡号)与 billingAddress(账单地址) 两个必须一起出现,不能只填一个。
python
from jsonschema import validate, ValidationError
# JSON Schema 规则
schema = {
"type": "object",
"properties": {
"creditCard": {"type": "string"},
"billingAddress": {"type": "string"}
},
"dependentRequired": {
"creditCard": ["billingAddress"]
}
}
# 合法数据
valid_data = {
"creditCard": "6222123456789012",
"billingAddress": "广东省深圳市南山区"
}
# 非法数据(只填信用卡,没有地址)
invalid_data = {
"creditCard": "6222123456789012"
}
# 校验合法数据
try:
validate(instance=valid_data, schema=schema)
print("✅ 合法数据:校验通过")
except ValidationError as e:
print("❌ 错误:", e.message)
# 校验非法数据
try:
validate(instance=invalid_data, schema=schema)
print("✅ 合法数据:校验通过")
except ValidationError as e:
print("❌ 错误:", e.message)
三、实战案例:接口返回 JSON 完整校验(博客列表接口)
3.1 原始接口返回 JSON 结构
python
{
"code": "SUCCESS",
"errMsg": "",
"data": [
{
"id": 1,
"title": "Python入门",
"content": "学习JSONSchema",
"userId": 1001,
"deleteFlag": 0,
"createTime": "2025-01-01",
"updateTime": "2025-01-02",
"loginUser": false
}
]
}
3.2 手写对应 JSONSchema 规则 + 完整可运行 Python 代码
python
import requests
from jsonschema.validators import validate
# 1. 定义整套接口返回的校验规则schema
blog_schema = {
"type": "object", # 整个返回体是对象
"required": ["code", "errMsg", "data"], # 三个字段必须存在
"additionalProperties": False, # 不能多出其他字段
"properties": {
"code": {"type": "string"}, # 状态码字符串
"errMsg": {"type": "string"}, # 错误提示字符串
"data": {
"type": "array", # data是数组
"items": { # 数组里每一项是博客对象
"type": "object",
"required": ["id","title","content","userId","deleteFlag","createTime","updateTime","loginUser"],
"additionalProperties":False,
"properties": {
"id": {"type": "number"},
"title": {"type": "string"},
"content": {"type": "string"},
"userId": {"type": "number"},
"deleteFlag": {"type": "number"},
"createTime": {"type": "string"},
"updateTime": {"type": "string"},
"loginUser": {"type": "boolean"}
}
}
}
}
}
# 2. 调用接口获取真实返回数据
url = "http://8.137.19.140:9090/blog/getList"
headers = {
"user_token_header": "eyJhbciOiJIUzI1NiJ9.eyJpZCI6MSwxNzkwNDc1NTk5NjE0OWFuY2hl"
}
res = requests.get(url=url, headers=headers)
resp_json = res.json()
# 3. 执行校验
try:
validate(instance=resp_json, schema=blog_schema)
print("✅ JSON格式完全符合规范,校验通过!")
except Exception as e:
print(f"❌ 校验失败,错误详情:{e.message}")
四、懒人技巧:JSON 自动转 JSONSchema 工具
手动写 schema 繁琐,推荐在线自动生成工具:
- 粘贴接口返回的 JSON 数据,一键生成基础 schema
- 重要提醒:工具生成结果需要二次修改(手动补充 required 必填、数值范围、正则等约束),不能直接拿来用。
五、自动化测试落地小技巧
- 用例分层:把每个接口的 schema 单独存为字典 / JSON 文件,测试用例直接读取,方便统一维护
- 异常捕获:try-except 捕获 validate 异常,测试报告输出详细错误信息(哪个字段类型错误、缺哪个必填项)
- 版本锁定 :安装固定
jsonschema==4.23.0,避免库升级后 API 改动导致旧代码报错
六、常见踩坑总结(小白必看)
- integer 和 number 区别:integer 只能整数,number 支持整数 + 小数,不要混用
- 布尔值小写:JSON 布尔是true/false(小写),不是 Python 的 True/False(JSON 数据规范)
- required 字段写错名字:字段名大小写敏感,errmsg和errMsg是两个不同字段
- 空值 null:字段允许为空写"type":"string","null",代表字符串或 null 都合法