9:JSONSchema

一、什么是 JSONSchema?

JSONSchema 是 JSON 数据的「规则说明书 + 校验器」

我们做接口自动化时,接口返回 JSON 格式数据,经常要校验:

  1. 返回字段有没有缺失(比如少了 code、data)
  2. 字段数据类型是否正确(code 是字符串、id 是数字,不能返回布尔 / 空)
  3. 字符串长度、数字范围、数组元素格式是否合规

**总结:**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 纯整数 1099(不能带小数)
number 数字 (整数 + 浮点) 203.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:管控必须存在哪些 key
  • min/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 繁琐,推荐在线自动生成工具:

https://tooltt.com/json2schema/

  1. 粘贴接口返回的 JSON 数据,一键生成基础 schema
  2. 重要提醒:工具生成结果需要二次修改(手动补充 required 必填、数值范围、正则等约束),不能直接拿来用。

五、自动化测试落地小技巧

  1. 用例分层:把每个接口的 schema 单独存为字典 / JSON 文件,测试用例直接读取,方便统一维护
  2. 异常捕获:try-except 捕获 validate 异常,测试报告输出详细错误信息(哪个字段类型错误、缺哪个必填项)
  3. 版本锁定 :安装固定jsonschema==4.23.0,避免库升级后 API 改动导致旧代码报错

六、常见踩坑总结(小白必看)

  1. integer 和 number 区别:integer 只能整数,number 支持整数 + 小数,不要混用
  2. 布尔值小写:JSON 布尔是true/false(小写),不是 Python 的 True/False(JSON 数据规范)
  3. required 字段写错名字:字段名大小写敏感,errmsg和errMsg是两个不同字段
  4. 空值 null:字段允许为空写"type":"string","null",代表字符串或 null 都合法
相关推荐
日晨难再1 小时前
C语言&Python&Bash&Tcl:全局变量和局部变量
c语言·python·bash·tcl
麻雀飞吧1 小时前
期货量化主连和具体合约怎么切:天勤 KQ.m 与 KQ.i 用法
python·区块链
先吃饱再说1 小时前
Python List 切片与 LLM Prompt 设计:从数据结构到接口调用
python
一只专注api接口开发的技术猿2 小时前
OpenClaw 对接淘宝商品 API,低成本实现全天候选品监控|附可运行 Python 实操代码
大数据·开发语言·数据库·python
xingpanvip2 小时前
星盘接口开发文档:马盘次限盘接口指南
android·开发语言·python·php·lua
FBI HackerHarry浩2 小时前
第二阶段Day07【Python生成器、yield关键字、property、正则表达式】
开发语言·python·正则表达式
梦想不只是梦与想2 小时前
Python 中的 4 种作用域
python·作用域
coderwei1232 小时前
从OpenAI到Strip:用六大支柱读懂Harness Engineering的生产实践
python·ai·ai编程
海鸥-w2 小时前
Python(FastAPI)中ORM框架Sqlalchemy的安装及建表
python