JSON Schema 接口数据校验 0基础快速入门
在接口测试中,如果每个字段都通过 assert 单独校验,不仅代码冗长,而且维护成本较高。JSON Schema 提供了一种标准化的数据校验方案,可以帮助我们快速验证接口返回结果是否符合预期。
一、什么是 JSON Schema?
JSON Schema 是一种用于描述和校验 JSON 数据结构的规范,可以理解为 JSON 数据的“规则说明书”。
例如你去水果店购买水果捞,老板规定:
- 必须包含西瓜和葡萄;
- 水果种类不能少于 3 种;
- 每种水果都必须填写名称和重量;
这些规则就相当于一个 Schema。
而水果捞本身则相当于 JSON 数据。
老板会根据这份规则检查你的水果捞是否符合要求,而 JSON Schema 的作用就是检查 JSON 数据是否符合预先定义好的规则。
二、基础校验:type 和 required
2.1 最简单的校验
from jsonschema import validate
json_schema = {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"}
}
}
# 即使缺少 age,校验也会通过(因为没有 required)
validate(instance={"name": "张三"}, schema=json_schema)
关键点: 没有 required 约束时,缺字段不会报错。
2.2 必填字段:required
json_schema = {
"type": "object",
"required": ["code", "data"],
"properties": {
"code": {"type": "string"},
"errMsg": {"type": "string"},
"data": {"type": "array"}
}
}
# code 和 data 必须存在
validate(instance={"code": "200", "data": []}, schema=json_schema)
required 是一个数组,列出所有必须存在的字段名。少一个就报错。
三、数组校验
3.1 数组元素类型
json_schema = {
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {"type": "integer"}
}
}
}
validate(instance={"data": [1, 2, 3]}, schema=json_schema)
3.2 数组长度与唯一性
json_schema = {
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {"type": "integer"},
"minItems": 5, # 最少 5 个
"maxItems": 10, # 最多 10 个
"uniqueItems": True # 元素必须唯一
}
}
}
# 通过:data = [1, 2, 3, 4, 5]
# 不通过:data = [1, 2, 3, 3, 5](3 重复了)
四、数组元素为对象
实际开发中,数组元素往往是对象,这时就要嵌套定义:
json_schema = {
"type": "object",
"required": ["code", "data"],
"properties": {
"code": {"type": "string"},
"data": {
"type": "array",
"items": {
"type": "object",
"required": ["id", "title", "author"],
"properties": {
"id": {"type": "integer"},
"title": {"type": "string"},
"author": {"type": "string"},
"content": {"type": "string"}
}
}
}
}
}
# 通过:[{"id": 1, "title": "博客1", "author": "张三"}]
# 不通过:[{"id": 1, "title": "博客1"}](缺少 author)
注意: required 可以出现在每一层,顶层对象有顶层的必填字段,嵌套对象有嵌套的必填字段。
五、数值约束
json_schema = {
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"exclusiveMinimum": 0, # id > 0
"exclusiveMaximum": 4 # id < 4
},
"age": {
"type": "integer",
"minimum": 10, # age >= 10
"maximum": 60 # age <= 60
}
}
}
}
}
}
| 关键字 | 含义 | 示例 |
|---|---|---|
minimum |
>= | minimum: 10 表示 ≥ 10 |
maximum |
<= | maximum: 60 表示 ≤ 60 |
exclusiveMinimum |
> | 表示大于,不能等于 |
exclusiveMaximum |
< | 表示小于,不能等于 |
记忆口诀: 前面加 exclusive 就是开区间(> 或 <),不加就是闭区间(>= 或 <=)。
六、字符串约束
json_schema = {
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 9, # 最少 9 个字符
"maxLength": 10 # 最多 10 个字符
},
"gender": {
"type": "string",
"enum": ["male", "female"] # 只能在这几个值中选
}
}
}
enum 限定字段的可选值,非常适合性别、状态码等有限选项的场景。
七、对象属性数量约束
7.1 minProperties / maxProperties
控制对象有多少个属性字段:
json_schema = {
"type": "object",
"minProperties": 2, # 至少 2 个字段
"maxProperties": 3, # 最多 3 个字段
"properties": {
"code": {"type": "string"},
"errMsg": {"type": "string"},
"data": {"type": "array"}
}
}
# 传 {code, errMsg, data} 3 个字段 → 通过
# 传 {code, errMsg, data, extra} 4 个字段 → 不通过
7.2 additionalProperties
控制是否允许 properties 中未定义的字段:
json_schema = {
"type": "object",
"properties": {
"id": {"type": "integer"},
"title": {"type": "string"}
},
"additionalProperties": True # 允许额外字段
# 如果设为 False,出现其他字段就会报错
}
八、依赖关系:dependentRequired
当一个字段出现时,要求另一个字段也必须出现:
json_schema = {
"type": "object",
"properties": {
"username": {"type": "string"},
"age": {"type": "integer", "minimum": 18, "maximum": 100},
"height": {"type": "integer", "minimum": 150, "maximum": 200},
"gender": {"type": "string", "enum": ["male", "female"]}
},
"dependentRequired": {
"age": ["height", "gender"]
}
}
# 传了 age,height 和 gender 也必须传
# 不传 age,height 和 gender 可以不存在
九、综合实战:博客接口响应校验
下面是一个完整的接口响应校验示例,结合了今天学的大部分知识点:
import requests
from jsonschema import validate
url = "http://47.97.164.187:9090/blog/getList"
header = {"user_token_header": "eyJhbGciOiJIUzI1NiJ9..."}
r = requests.get(url, headers=header)
json_schema = {
"type": "object",
"required": ["code", "errMsg", "data"],
"minProperties": 2,
"maxProperties": 3,
"properties": {
"code": {"type": "string"},
"errMsg": {"type": "string"},
"data": {
"type": "array",
"items": {
"type": "object",
"required": [
"id", "title", "content", "userId",
"deleteFlag", "createTime", "updateTime", "loginUser"
],
"minProperties": 7,
"maxProperties": 9,
"additionalProperties": True,
"properties": {
"id": {"type": "integer", "exclusiveMinimum": 0},
"title": {"type": "string", "minLength": 1},
"content": {"type": "string"},
"userId": {"type": "integer", "minimum": 1},
"deleteFlag": {"type": "integer", "enum": [0, 1]},
"createTime": {"type": "string"},
"updateTime": {"type": "string"},
"loginUser": {"type": "boolean"}
}
}
}
}
}
validate(r.json(), json_schema)
print("接口数据校验通过!")
十、总结
| 知识点 | 关键字 | 用途 |
|---|---|---|
| 类型 | type |
指定字段类型(string, integer, number, boolean, array, object) |
| 必填 | required |
指定哪些字段必须存在 |
| 字符串长度 | minLength / maxLength |
控制字符串长度 |
| 数值范围 | minimum / maximum |
控制数值范围(闭区间) |
| 数值范围 | exclusiveMinimum / exclusiveMaximum |
控制数值范围(开区间) |
| 数组长度 | minItems / maxItems |
控制数组元素个数 |
| 数组唯一 | uniqueItems |
数组元素是否必须唯一 |
| 属性数量 | minProperties / maxProperties |
控制对象字段个数 |
| 额外属性 | additionalProperties |
是否允许未定义的字段 |
| 枚举 | enum |
限定可取值列表 |
| 依赖 | dependentRequired |
字段出现时的连带必填 |
JSON Schema 就像是给 JSON 数据上的一份"体检单"——通过它,你可以精确地把控接口数据的质量,在自动化测试中尤为实用。写接口测试时,用 Schema 校验代替单纯的字段存在性检查,能让你的测试更严谨、更专业!
十一、问答练习
11.1 type 类型校验
题目: 以下 Schema 中,传 {"age": 20.5} 能通过校验吗?
{"type": "object", "properties": {"age": {"type": "integer"}}}
不能通过。 20.5 是浮点数类型,但 Schema 要求 integer(整数)。在 JSON Schema 中 integer只能是整数 number既可以是整数也可以是浮点数。
11.2 required 必填字段
题目: 传 {}(空对象)能通过吗?
{"type": "object", "required": ["name"], "properties": {"name": {"type": "string"}}}
不能通过。 required 要求 name 字段必须存在,所以最少都要传name字段才可以通过。
11.3 minLength / maxLength 字符串长度
题目: "name": "hello" 能通过吗?
"name": {"type": "string", "minLength": 5, "maxLength": 10}
能通过。 "hello" 长度为 5,满足 minLength: 5(≥5)且 maxLength: 10(≤10)。
11.4 minimum / maximum 数值范围
题目: age: 18 能通过吗?age: 60 呢?
"age": {"type": "integer", "minimum": 18, "maximum": 60}
都能通过。 minimum: 18 表示 ≥18,maximum: 60 表示 ≤60,18 和 60 都在闭区间 [18, 60] 内,临界值18与60可以通过校验。
11.5 exclusiveMinimum / exclusiveMaximum 数值范围
题目: id: 0 和 id: 1 哪个能通过?
"id": {"type": "integer", "exclusiveMinimum": 0}
id: 1 能通过,id: 0 不能。 exclusiveMinimum: 0 表示 id > 0,因此 0 无法通过校验,而 1 可以通过。exclusiveMinimum 和 exclusiveMaximum 表示不包含边界值,即临界值本身无法通过校验。
11.6 minItems / maxItems 数组长度
题目: data: [1, 2] 能通过吗?
"data": {"type": "array", "items": {"type": "integer"}, "minItems": 3, "maxItems": 5}
不能通过。 minItems: 3 要求数组至少 3 个元素,实际data中只有 2 个。
11.7 uniqueItems 数组唯一性
题目: data: [1, 2, 3, 2] 能通过吗?
"data": {"type": "array", "items": {"type": "integer"}, "uniqueItems": True}
不能通过。 uniqueItems: True 要求数组元素全部唯一,但 2 出现了两次。
11.8 minProperties / maxProperties 对象属性数量
题目: 传 {"a": 1, "b": 2, "c": 3, "d": 4} 能通过吗?
{"type": "object", "minProperties": 2, "maxProperties": 3}
不能通过。 规定了字段数量在[2,3]之间,现在传过来的有 4 个字段,超过了 maxProperties: 3 的限制。
11.9 additionalProperties 额外属性
题目: 传 {"id": 1, "title": "A", "extra": "x"} 能通过吗?
{
"type": "object",
"properties": {"id": {"type": "integer"}, "title": {"type": "string"}},
"additionalProperties": False
}
不能通过。 additionalProperties: False 禁止出现 properties 中未定义的字段,extra 不在定义中。
11.10 enum 枚举
题目: gender: "other" 能通过吗?
"gender": {"type": "string", "enum": ["male", "female"]}
不能通过。 enum 限定了只能取 "male" 或 "female","other" 不在列表中。
11.11 dependentRequired 依赖关系
题目: 传 {"age": 20} 能通过吗?
{
"type": "object",
"properties": {"age": {"type": "integer"}, "height": {"type": "integer"}},
"dependentRequired": {"age": ["height"]}
}
不能通过。 dependentRequired 规定:如果传了 age,则 height 也必须传。这里传了 age 但缺少 height。但是反过来传了"height"字段,如果没有其他特殊设置"age"不传过来也是可以的
11.12 综合实战题
题目: 以下 JSON 能通过校验吗?指出所有问题。
json = {
"code": "200",
"data": [
{"id": 0, "title": "a"},
{"id": 2, "title": "bb", "author": "李四"}
]
}
schema = {
"type": "object",
"required": ["code", "data"],
"properties": {
"code": {"type": "string"},
"data": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": ["id", "title", "author"],
"properties": {
"id": {"type": "integer", "exclusiveMinimum": 0},
"title": {"type": "string", "minLength": 2},
"author": {"type": "string"}
}
}
}
}
}
不能通过,第一个元素存在三个问题:
id: 0— 不满足exclusiveMinimum: 0(需要 id > 0)title: "a"— 长度为 1,不满足minLength: 2- 缺少
author—required中要求了author字段
第二个元素 {"id": 2, "title": "bb", "author": "李四"} 校验全部通过
由于数组中有一个元素校验失败,整体校验不通过。修正建议:将第一个元素的 id 改为 ≥1,title 补足 2 个字符以上,并补上 author 字段。
以上答案仅供参考,是我个人根据学习的内容整理的,如果有不同的见解,或是发现我有错误的地方,欢迎探讨。😃
更多推荐

所有评论(0)