3. JSON Schema 入门:定义 Redis Value 的契约
在 Redis 契约校验体系中,JSON Schema 是描述 Value 结构最核心的语言。它不关心数据如何存储,只关心数据“应该长什么样”。本章从零开始,掌握 JSON Schema 的基本语法、关键字,并学会为 Redis Value 编写精确的 Schema 定义。
3.1 什么是 JSON Schema
JSON Schema 是一种基于 JSON 格式的声明式语言,用于描述 JSON 数据的结构、类型和约束。你可以把它理解为“数据的身份证”——它规定了某个 JSON 对象必须包含哪些字段、字段的类型是什么、取值范围是多少。
核心思想:JSON Schema 本身也是一个 JSON 对象,通过特定的关键字(如
type、properties、required)来描述另一个 JSON 数据的规则。
3.2 基本语法与结构
一个最简单的 JSON Schema 通常包含以下结构:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://example.com/user-schema.json",
"title": "User Profile",
"description": "用户基本信息 Schema",
"type": "object",
"properties": {
"username": { "type": "string" },
"age": { "type": "integer" }
},
"required": ["username"]
}
| 关键字 | 作用 | 是否必须 |
|---|---|---|
$schema |
声明使用的 Schema 规范版本 | 推荐 |
$id |
Schema 的唯一标识 URI | 可选 |
title |
Schema 的简短标题 | 可选 |
description |
Schema 的详细说明 | 可选 |
type |
定义数据的类型(string、number、object、array、boolean、null) | 必须 |
properties |
定义对象类型下的各个字段 | 当 type 为 object 时使用 |
required |
声明哪些字段是必须存在的 | 可选 |
3.3 核心关键字详解
3.3.1 类型约束
type 是最基础的关键字,支持以下 7 种类型:
- string — 字符串
- number — 数字(整数或浮点数)
- integer — 整数
- boolean — 布尔值
- object — 对象
- array — 数组
- null — 空值
注意:Redis 中存储的 JSON 值通常为 object 或 array 类型。如果 Value 是简单字符串或数字,Schema 只需定义
type 即可。
3.3.2 字符串约束
| 关键字 | 说明 | 示例 |
|---|---|---|
minLength |
最小长度 | "minLength": 1 |
maxLength |
最大长度 | "maxLength": 100 |
pattern |
正则表达式匹配 | "pattern": "^[a-zA-Z0-9]+$" |
format |
预定义格式(email、date-time、uri 等) | "format": "email" |
enum |
枚举值列表 | "enum": ["admin", "user", "guest"] |
3.3.3 数字约束
| 关键字 | 说明 | 示例 |
|---|---|---|
minimum |
最小值(包含) | "minimum": 0 |
maximum |
最大值(包含) | "maximum": 150 |
exclusiveMinimum |
最小值(不包含) | "exclusiveMinimum": 0 |
exclusiveMaximum |
最大值(不包含) | "exclusiveMaximum": 100 |
multipleOf |
必须是某数的倍数 | "multipleOf": 5 |
3.3.4 数组约束
| 关键字 | 说明 | 示例 |
|---|---|---|
items |
定义数组元素的 Schema | "items": { "type": "string" } |
minItems |
最小元素个数 | "minItems": 1 |
maxItems |
最大元素个数 | "maxItems": 10 |
uniqueItems |
元素是否必须唯一 | "uniqueItems": true |
3.3.5 对象约束
| 关键字 | 说明 | 示例 |
|---|---|---|
properties |
定义每个字段的 Schema | "properties": { "name": { "type": "string" } } |
required |
必须存在的字段列表 | "required": ["name", "email"] |
additionalProperties |
是否允许未定义的字段 | "additionalProperties": false |
minProperties |
对象最少字段数 | "minProperties": 1 |
maxProperties |
对象最多字段数 | "maxProperties": 20 |
3.4 如何定义 Redis Value 的 Schema
在 Redis 中,Value 可以是任意 JSON 结构。定义 Schema 时,需要先确定 Value 的顶层类型,然后逐层描述内部字段。
步骤流程:
- 确定顶层类型 — 通常是
object或array - 列出所有字段 — 使用
properties定义每个字段 - 标记必填字段 — 使用
required列出必须存在的字段名 - 约束字段类型 — 为每个字段设置
type和附加约束 - 控制额外字段 — 使用
additionalProperties决定是否允许未声明的字段
实战案例:假设 Redis 中存储了一个用户会话对象,Value 结构如下:
{
"userId": "u_1001",
"role": "admin",
"loginCount": 42,
"tags": ["vip", "2024"],
"profile": {
"nickname": "Alice",
"avatar": "https://example.com/avatar.png"
}
}
对应的 Schema 定义:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "User Session",
"type": "object",
"properties": {
"userId": {
"type": "string",
"pattern": "^u_\\d+$",
"description": "用户ID,以 u_ 开头"
},
"role": {
"type": "string",
"enum": ["admin", "user", "guest"]
},
"loginCount": {
"type": "integer",
"minimum": 0
},
"tags": {
"type": "array",
"items": { "type": "string" },
"minItems": 1,
"uniqueItems": true
},
"profile": {
"type": "object",
"properties": {
"nickname": { "type": "string", "minLength": 1 },
"avatar": { "type": "string", "format": "uri" }
},
"required": ["nickname"],
"additionalProperties": false
}
},
"required": ["userId", "role", "loginCount"],
"additionalProperties": false
}
3.5 JSON Schema 校验流程
3.6 常见避坑指南
⚠️ 常见错误 1:忘记设置
默认情况下,
additionalProperties默认情况下,
additionalProperties 为 true,意味着对象可以包含任何未在 properties 中声明的字段。如果希望严格约束,必须显式设置为 false。
⚠️ 常见错误 2:
required 与 properties 不匹配required 中列出的字段名必须在 properties 中有定义,否则校验器会报错。
💡 最佳实践:为每个 Redis Key 的 Value 单独编写 Schema,并存储在独立的
.json 文件中。在应用启动时加载到内存,避免每次校验都读取磁盘。
3.7 本章小结
- JSON Schema 是描述 JSON 数据结构的声明式语言,核心关键字包括
type、properties、required、additionalProperties等。 - 字符串、数字、数组、对象各有专属约束关键字,如
pattern、minimum、minItems、uniqueItems。 - 定义 Redis Value 的 Schema 时,先确定顶层类型,再逐层描述字段,最后通过
required和additionalProperties控制严格程度。 - 校验流程分为加载 Schema、逐字段校验、输出通过/失败结果三个步骤。