什么是 JSON?语法、数据类型、JavaScript 对象与 JSON Schema
学会 JSON 的语法和数据类型,看懂合法示例,弄清 JSON 与 JavaScript 对象的区别,并用 JSON Schema 校验真实的数据约定。
JSON,全称 JavaScript Object Notation,是一种用于在应用之间交换结构化数据的文本格式。它不是数据库,不是编程语言,也不是 schema。当一个系统要把数据交给另一个系统时,放到网络上传输、或者存进文件里的那段文本,就是 JSON。
如果你打开过 package.json、看过 REST 接口的响应、拷过 Webhook 载荷、改过 VS Code 的设置文件,或者瞄过浏览器的 Network 面板,那你早就见过 JSON 了。一个好用的心智模型很简单:JSON 是序列化之后的数据值。一个程序在发送前把对象变成 JSON 文本,另一个程序再把这段文本解析回自己语言里的数据结构。
{
"id": "usr_42",
"name": "Ada Lovelace",
"active": true,
"roles": ["admin", "editor"],
"profile": {
"timezone": "Europe/London",
"newsletter": false
}
}
这个例子是合法 JSON,因为它是一个完整的值、键和字符串都用双引号、true 和 false 是小写,而且只包含 JSON 的数据类型。
一分钟看懂 JSON
| 问题 | 实用答案 |
|---|---|
| JSON 是什么的缩写? | JavaScript Object Notation |
| JSON 用来干什么? | API 响应、请求体、配置文件、日志、数据导出,以及服务之间的消息 |
| JSON 只能给 JavaScript 用吗? | 不是。所有主流语言都能解析和生成它 |
| JSON 和 JavaScript 对象是一回事吗? | 不是。JSON 是语法更严格的文本,JavaScript 对象字面量是代码 |
| JSON 有几种数据类型? | 六种:对象、数组、字符串、数字、布尔、null |
| JSON 文件可以以数组开头吗? | 可以。JSON 文本可以是任意单个 JSON 值,只是对象和数组最常见 |
| JSON 能写注释吗? | 不能。注释属于 JSONC,不属于严格 JSON |
| 怎么校验 JSON? | 用 JSON 解析器解析它,或者用严格的 JSON 校验器 |
什么是 JSON
JSON 是一套用来表示结构化数据的标准化文本语法。RFC 8259 把 JSON 描述为一种轻量、基于文本、与语言无关的数据交换格式。ECMA-404 定义了同一套核心语法,并有意把"这些数据是什么意思"留给使用它的系统去决定。
最后这点很关键。JSON 只告诉你数据该怎么写:
{
"total": 1299,
"currency": "USD"
}
它不告诉你 1299 到底是美元、美分、积分,还是库存件数。赋予数据含义的,是你的 API 约定、文档、JSON Schema、OpenAPI 规范或数据库模型。
一份 JSON 文档就是一个值
合法的 JSON 文档里,顶层有且只有一个 JSON 值。大多数真实文档用的是对象:
{
"status": "ok",
"items": []
}
数组也很常见:
[
{ "id": 1, "name": "Alice" },
{ "id": 2, "name": "Bob" }
]
基础类型同样是合法 JSON:
42
"hello"
null
实践中,API 响应通常还是套一层对象,因为这样才放得下元数据、分页信息、错误,以及将来要加的字段:
{
"data": [
{ "id": 1, "name": "Alice" }
],
"meta": {
"page": 1,
"hasMore": false
}
}
JSON 的六种数据类型
JSON 有四种基础类型和两种结构类型,合起来常被称作 JSON 的六种数据类型。
| 类型 | 示例 | 用来表示 | 注意 |
|---|---|---|---|
| 对象 | { "id": 1 } |
具名字段和嵌套记录 | 键必须是字符串;重复键很危险 |
| 数组 | [1, 2, 3] |
有序列表 | 元素类型可以不一致,但混合数组更难用 |
| 字符串 | "Ada" |
文本、ID、日期、十进制金额 | 必须用双引号,转义要合法 |
| 数字 | 42、3.14、1.5e10 |
计数、度量、安全范围内的数值 | 不能有 NaN、Infinity、十六进制、前导零 |
| 布尔 | true、false |
二元状态 | 只能小写 |
| Null | null |
明确表示"空值" | 和"键不存在"不是一回事 |
对象
对象是用 {} 包起来的一组名值对。名字是字符串,所以必须加双引号。
{
"name": "Alice",
"age": 30,
"active": true
}
RFC 8259 规定对象的名字应当唯一。很多解析器照样接受重复键,但它们的行为并不一致:有的保留最后一个值,有的保留第一个,有的把所有键值对都暴露出来。
别这么写:
{
"role": "user",
"role": "admin"
}
一个键要是重要,就只写一次。
数组
数组是用 [] 包起来的有序列表。
["apple", "banana", "cherry"]
数组里可以放对象:
[
{ "sku": "hat-blue", "quantity": 2 },
{ "sku": "mug-white", "quantity": 1 }
]
JSON 允许混合类型的数组:
["ok", 200, true, null]
语法上确实允许,但对有类型的代码、CSV 导出、分析程序和生成的 TypeScript 接口来说,这往往很别扭。在 API 设计里,元素类型一致的数组通常更好维护。
字符串
字符串是双引号里的 Unicode 文本。
"Hello, world!"
单引号不是 JSON:
'Hello, world!'
字符串内部的引号、反斜杠和控制字符必须转义:
{
"quote": "She said \"hello\".",
"path": "C:\\Users\\Ada\\notes.json",
"lines": "first line\nsecond line"
}
如果某个东西长得像数字,但它其实是标识符(账号 ID、订单号、邮政编码、电话号码、外部系统的大 ID),就把它当字符串。这些值本来就不用来做算术,而字符串形式还能顺便避开前导零和精度问题。
数字
JSON 只有一种数字类型。
{
"count": 42,
"ratio": 0.875,
"scientific": 1.5e10
}
数字是十进制的。JSON 不允许十六进制、八进制、NaN、Infinity,也不允许前导零:
{
"hex": 0xff,
"nan": NaN,
"badLeadingZero": 007
}
对 JavaScript 客户端来说,大于 9007199254740991(即 Number.MAX_SAFE_INTEGER)的整数要格外小心。如果某个 ID 可能超过这个范围,就用字符串传:
{
"invoiceId": "9223372036854775807"
}
金额优先用整数最小单位,或者有明确文档说明的十进制字符串:
{
"amountCents": 1299,
"currency": "USD"
}
布尔
JSON 的布尔值只有 true 和 false。
{
"emailVerified": true,
"smsOptIn": false
}
True、False、yes、no、1、0 都不是 JSON 布尔值。它们在 Python、YAML、SQL、表单或表格软件里可能有意义,但严格 JSON 解析器要么拒绝它们,要么按别的类型处理。
Null
null 的意思是"这个字段在,但值是空的"。
{
"middleName": null
}
它和"干脆不写这个键"不一样:
{}
在 API 约定里,你得想清楚自己要表达哪一种:
| 写法 | 含义 |
|---|---|
"middleName": null |
字段存在,但没有值 |
没有 middleName 这个键 |
字段未知、未请求,或不适用 |
"middleName": "" |
值是一个空字符串 |
这个区别在 PATCH 请求、表单提交、生成类型和数据库更新里都很要紧。
真正会咬人的 JSON 语法规则
严格 JSON 被刻意设计得很小。下面这些是开发者最常撞上的规则:
| 规则 | 非法 | 合法 |
|---|---|---|
| 键必须是双引号字符串 | { name: "Alice" } |
{ "name": "Alice" } |
| 字符串用双引号 | { "name": 'Alice' } |
{ "name": "Alice" } |
| 不能有尾随逗号 | { "a": 1, } |
{ "a": 1 } |
| 不能有注释 | { "a": 1 // note } |
{ "a": 1 } |
| 字面量只能小写 | { "ok": True } |
{ "ok": true } |
不能有 undefined |
{ "x": undefined } |
{ "x": null } |
| 顶层只能有一个值 | {} {} |
[{ }, { }] |
token 之间的空白是无意义的。下面两份文档解析出来是同一个值:
{"name":"Alice","active":true}
{
"name": "Alice",
"active": true
}
格式化让 JSON 更好读,但它不改变数据。
.json 文件是什么
.json 文件就是一个纯文本文件,内容是一份 JSON 文档。它不需要文件头、schema 声明、import 语句,也不需要结束标记。把合法的 JSON 文本存成 .json 扩展名,绝大多数工具就认了。
常见的例子:
| 文件 | 通常装的是什么 |
|---|---|
package.json |
Node.js 的包元数据、脚本和依赖 |
tsconfig.json |
TypeScript 编译器选项 |
manifest.json |
浏览器扩展或 PWA 的元数据 |
appsettings.json |
.NET 应用配置 |
composer.json |
PHP 包元数据 |
打开 JSON 文件可以用文本编辑器、IDE、终端命令,或者 JSON 查看器。要新建一个,写一个合法的 JSON 值,存成 name.json 即可。
比如 users.json 里可能是:
[
{ "id": "usr_1", "name": "Alice", "role": "admin" },
{ "id": "usr_2", "name": "Bob", "role": "editor" }
]
文件很大或嵌套很深时,树形查看器通常比在原始文本里滚动省事得多。
JSON 与 JavaScript 对象字面量
JSON 长得像 JavaScript,但它们不是一回事。
这是 JavaScript 对象字面量:
const user = {
id: 42,
name: "Alice",
active: true,
lastSeen: undefined,
greet() {
return `Hello ${this.name}`;
},
};
这是 JSON:
{
"id": 42,
"name": "Alice",
"active": true
}
JSON 里不能有函数、方法、注释、尾随逗号、undefined、Symbol、Date 对象、Map、Set 或计算属性名。它只承载数据。
在 JavaScript 里,用 JSON.parse() 和 JSON.stringify() 在两者之间转换:
const text = '{"name":"Alice","active":true}';
const value = JSON.parse(text);
const output = JSON.stringify(value, null, 2);
如果你手上已经是对象,就别调用 JSON.parse(object);需要 JSON 文本时,调用 JSON.stringify(object)。
在代码里解析和生成 JSON
所有主流语言都内置了 JSON 支持。
JavaScript:
const raw = '{"name":"Alice","age":30}';
const user = JSON.parse(raw);
const text = JSON.stringify(user);
Python:
import json
raw = '{"name":"Alice","age":30}'
user = json.loads(raw)
text = json.dumps(user)
Go:
package main
import "encoding/json"
type User struct {
Name string `json:"name"`
Age int `json:"age"`
}
func main() {
var user User
_ = json.Unmarshal([]byte(`{"name":"Alice","age":30}`), &user)
}
处理文件时,用支持文件的解析器,别自己读几块就急着解析。Python 里 json.load(file) 从文件对象读 JSON,json.loads(text) 解析字符串。
JSON 都用在哪儿
JSON 成为默认数据格式,是因为它对机器来说足够小、对人来说足够好读,而且几乎每种编程语言都支持。
常见用途:
- API 的请求体和响应体,通常带
Content-Type: application/json。 - 支付服务商、认证服务商和各类 SaaS 发来的 Webhook。
- 构建工具、编辑器、命令行工具和云服务的配置文件。
- 结构化日志,常见形式是 JSON Lines 或 NDJSON。
- 分析工具、数据库和内部管理系统的数据导出。
- 服务、队列、Serverless 函数和 worker 之间的消息。
- 应用仓库里的测试数据。
数据是层级结构、而且消费方清楚约定时,JSON 很合适。但它不适合富文本文档、注释很多的人工配置、二进制文件、表格式数据,以及那些需要严格数值精度却又没约定好表示方式的数据。
数据库里的 JSON
现代数据库可以直接存 JSON,但这不代表每个字段都该塞进一个巨大的 JSON blob。
实用的模式:
- 经常用来过滤、连表或排序的稳定字段,存成普通列。
- 灵活的元数据、事件属性、集成载荷或用户偏好,存成 JSON。
- 给你频繁查询的那些 JSON 路径建索引。
- 在应用边界上先校验结构,别把乱七八糟的文档写进去。
各数据库的情况:
- PostgreSQL 有
json和jsonb,做索引和包含查询时通常jsonb更好。 - MySQL 有原生
JSON类型和JSON_EXTRACT这类路径函数。 - SQLite 提供
json_extract、json_each等 JSON 函数。 - MongoDB 用 BSON 存文档 —— 一种类 JSON 的二进制格式,还多了些额外类型。
两点提醒:JSON 对象的键顺序不能拿来当业务规则;也不要用重复键去表示多个值 —— 要表示多个值,请用数组。
JSON、XML 与 YAML
JSON、XML 和 YAML 都能传输结构化数据,但在真实项目里手感很不一样。
| 格式 | 最适合 | 代价 |
|---|---|---|
| JSON | API、Web 应用、给程序读的配置 | 不能写注释、语法严格、数据类型有限 |
| XML | 文档标记、命名空间、较老的企业协议 | 冗长,解析开销更大 |
| YAML | 人工编辑的配置 | 缩进和隐式类型推断容易给人惊喜 |
同一个用户,用 JSON 表示:
{
"name": "Alice",
"age": 30
}
用 XML 表示:
<user>
<name>Alice</name>
<age>30</age>
</user>
JSON 在绝大多数 Web API 场景里胜出,因为它紧凑、能干净地映射到常见语言的数据结构,而且浏览器 JavaScript 里就内置了。XML 在偏文档的格式、SOAP、RSS、SAML 以及使用命名空间的系统里依然重要。YAML 对人工编辑配置更友好;但当很多语言和工具需要就"数据到底长什么样"达成一致时,严格 JSON 更稳妥。
常见的 JSON 变体
严格 JSON 是基准线,另外还有几种经常出现的相关格式:
| 变体 | 改了什么 | 怎么解析 |
|---|---|---|
| JSONC | 加了注释,通常也允许尾随逗号 | 用 JSONC 解析器;别把它当 API 的 JSON 发出去 |
| JSON5 | 加了更多类 JavaScript 的语法 | 交换之前先转成严格 JSON |
| NDJSON / JSON Lines | 每行一个 JSON 值 | 按行切分,逐行解析 |
| JSON Schema | 描述合法的 JSON 结构 | 用 schema 校验器 |
| JSON Pointer | 定位 JSON 内部的某个值,比如 /users/0/name |
当作路径记法使用,它本身不是 JSON |
| JSON Patch | 描述对 JSON 文档的修改 | 用 JSON Patch 库来应用这些操作 |
别把它们当成同一种文件格式。tsconfig.json 之所以能写注释,是因为 TypeScript 工具链是按 JSONC 解析它的;而对外的 API 响应,仍然必须是严格 JSON。
常见的 JSON 错误
载荷解析失败时,我会优先检查这几项:
| 症状 | 示例 | 怎么修 |
|---|---|---|
| 单引号 | { 'name': 'Alice' } |
改用双引号 |
| 没加引号的键 | { name: "Alice" } |
每个键都加引号 |
| 尾随逗号 | { "a": 1, } |
删掉最后那个逗号 |
| 注释 | { "a": 1 // note } |
删掉注释,或在支持的场合改用 JSONC |
| Python 字面量 | { "ok": True, "x": None } |
改成 true 和 null |
| undefined | { "x": undefined } |
要么省略这个键,要么用 null |
| 两份文档挨在一起 | {} {} |
包进数组,或当成两条独立消息分别解析 |
| 字符串里有真实换行 | "line one 后面直接换行 |
改用 \n |
粘贴进来的示例,JSON Fix 能在你的浏览器本地修掉常见语法问题。而 API 约定和生产流程,请去修生产方并校验结果,别默默地接受格式错误的数据。
先校验语法,再校验含义
JSON 语法校验回答的问题非常窄:这段文本能被某个严格解析器读进去吗?下面这些命令做的都是这道关卡:
const value = JSON.parse(rawText);
python3 -m json.tool data.json >/dev/null
jq empty data.json
解析不过,就去修语法或者修生产方。解析过了,你手上有了一个 JSON 值,但它未必有用、也未必安全。下面这份载荷在 JSON 语法上完全合法:
{
"email": "not-an-email",
"age": -4,
"role": "owner-of-everything"
}
至于它对你的应用来说合不合法,那是另一个问题 —— 这就轮到 JSON Schema 登场了。
什么是 JSON Schema
JSON Schema 是一份机器可读的 JSON 数据约定。它描述哪些字段必填、允许哪些类型和取值、数组该是什么形状,以及要不要接受未知属性。
这几层值得分清楚:
| 层次 | 问题 | 常用工具 |
|---|---|---|
| JSON 解析 | 这是合法的 JSON 文本吗? | JSON.parse、json.loads、jq |
| JSON Schema | 解析出来的值符合文档约定的结构吗? | Ajv、Python 的 jsonschema |
| 业务校验 | 这个操作此刻被允许、且有意义吗? | 应用代码、数据库、授权规则 |
JSON Schema 本身也是 JSON。下面这份 Draft 2020-12 的 schema 描述了一条小小的用户记录:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["id", "email", "role"],
"properties": {
"id": {
"type": "string",
"pattern": "^usr_[0-9]+$"
},
"email": {
"type": "string",
"format": "email"
},
"role": {
"enum": ["admin", "editor", "viewer"]
}
},
"additionalProperties": false
}
这个值符合它:
{
"id": "usr_42",
"email": "ada@example.com",
"role": "admin"
}
这份 schema 把好几条原本靠默契的假设变成了可执行的规则:三个字段都必须存在、id 要符合已知的模式、role 只能从固定列表里取,而多出来的字段一律拒绝。
最先会用到的 JSON Schema 关键字
大多数实用的 schema 都从一小撮词汇开始。
| 关键字 | 控制什么 | 常见误区 |
|---|---|---|
$schema |
使用的 schema 草案或方言 | 干脆不写,让工具自己猜 |
type |
JSON 值的类型 | 忘了 integer 不包含小数 |
properties |
具名对象字段的规则 | 以为写了它这些字段就成必填了 |
required |
必须存在的键 | 重要字段只写在 properties 里 |
items |
数组元素的规则 | 忘了约束嵌套对象 |
enum |
一组固定的允许取值 | 拿它去管一个经常变动的列表 |
additionalProperties |
是否允许未知的对象键 | 对外响应对象封得太死 |
$defs 和 $ref |
可复用的 schema 片段 | 改了共享的 $id 却不当成破坏性变更 |
properties 和 required 解决的是不同的问题。下面这份 schema 并不要求 email 必填:
{
"type": "object",
"properties": {
"email": { "type": "string" }
}
}
它只是说:email 如果出现,就必须是字符串。存在性重要的话,请加上 "required": ["email"]。
在独立的 JSON Schema 里表示可空值,把两种类型都列出来:
{
"type": ["string", "null"]
}
另外别以为 default 会帮你把缺失的数据补上。在 JSON Schema 里它只是个注解 —— 除非你的校验器提供了明确的、非标准的写入选项。
在 JavaScript 里做 schema 校验
Ajv 是 JavaScript 和 TypeScript 项目里常用的校验器。用 Draft 2020-12 时,要用配套的构造函数:
npm install ajv ajv-formats
import Ajv2020 from "ajv/dist/2020.js";
import addFormats from "ajv-formats";
const ajv = new Ajv2020({ allErrors: true });
addFormats(ajv);
const schema = {
$schema: "https://json-schema.org/draft/2020-12/schema",
type: "object",
required: ["id", "email"],
properties: {
id: { type: "string" },
email: { type: "string", format: "email" }
},
additionalProperties: false
};
const validate = ajv.compile(schema);
const data = { id: "usr_42", email: "ada@example.com" };
if (!validate(data)) {
console.error(validate.errors);
}
schema 编译一次,然后复用那个校验函数。在表单、测试和开发者工具里,allErrors: true 能一次性给出完整的问题清单,省得别人跑一次改一个字段。
在 Python 里做 schema 校验
Python 的 jsonschema 包支持 Draft 2020-12 的校验器:
pip install jsonschema
from jsonschema import Draft202012Validator, FormatChecker
schema = {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["id", "email"],
"properties": {
"id": {"type": "string"},
"email": {"type": "string", "format": "email"},
},
"additionalProperties": False,
}
data = {"id": "usr_42", "email": "ada@example.com"}
validator = Draft202012Validator(schema, format_checker=FormatChecker())
errors = sorted(validator.iter_errors(data), key=lambda error: error.path)
for error in errors:
print(list(error.path), error.message)
需要把每个有问题的字段都报出来时,用 iter_errors 比较合适。如果你要的就是"一出错立刻失败",那调一次 validate() 就够了。
schema 校验不等于授权
再完美的 schema,也证明不了某个邮箱真的收得到信、某个用户 ID 真的存在、某个 SKU 真的有货,或者调用方真的有权修改这个账户。它同样不能保证一个字符串放进 HTML 里是安全的。
把 JSON Schema 当作边界检查。之后在应用代码里再补上认证、授权、数据库查询、跨字段规则、内容清洗和副作用管控。结构很重要,但它不是约定的全部。
快速语法检查用 JSON 校验器。输入里混着注释、单引号或尾随逗号时,先用 JSON Fix 修好再套 schema。想看解析后的结构用 JSON 查看器,需要可读输出时看如何格式化 JSON。
常见问题
JSON 是什么的缩写?
JSON 是 JavaScript Object Notation 的缩写。虽然名字里有 JavaScript,但它与语言无关 —— JavaScript、Python、Go、Java、Ruby、Rust、PHP、数据库、命令行工具和浏览器都能读写它。
JSON 用来做什么?
API 的请求体和响应体、Webhook、应用配置、包元数据、结构化日志、数据导出、测试数据,以及服务之间的消息,都用 JSON 来写。
JSON 有哪些数据类型?
JSON 有六种值类型:对象、数组、字符串、数字、布尔和 null。它没有日期类型,没有单独的整数类型,没有 undefined,没有函数类型,没有注释类型,也没有 Map、Set 或二进制类型。
JSON 和 JavaScript 对象是一回事吗?
不是。JSON 是文本,语法非常严格;JavaScript 对象字面量是代码。JavaScript 对象字面量支持、而 JSON 不支持的东西包括:注释、尾随逗号、不加引号的键、函数、undefined、Date 对象和计算属性名。
JSON 文件可以以数组开头吗?
可以。JSON 文档可以是任意 JSON 值,数组当然也行 —— 数组、字符串、数字、布尔和 null 都是合法的 JSON。API 响应之所以常用对象,是因为它给元数据留了扩展空间。
JSON 支持注释吗?
不支持。严格 JSON 不允许注释。有些工具在人工编辑的配置里用 JSONC 或 JSON5,但这些文件在通过 API 传输、或交给普通 JSON 解析器之前,需要先转成严格 JSON。
怎么确认 JSON 是合法的?
用 JSON.parse()、python3 -m json.tool、jq empty,或者一个严格的 JSON 校验器。如果还要校验必填字段和类型,那就在语法解析之后用 JSON Schema。
JSON 里 null 和"键不存在"有什么区别?
null 表示键在,但值被有意置空。键不存在,则意味着这个字段没被提供、没被请求、不知道,或者不适用。API 约定里应该写清楚自己用的是哪一种。
JSON Schema 是干什么用的?
JSON Schema 用来描述和校验 JSON 约定:必填字段、允许的类型、枚举、数值范围、数组形状、嵌套对象,以及可复用的定义。
写了 properties 字段就变成必填了吗?
不会。properties 只在键存在时施加规则。键必须存在的话,请把它加进 required。
format: "email" 一定会拒绝错误的邮箱字符串吗?
不一定。format 的行为取决于校验器及其配置。如果你确实需要它拒绝,请启用 format 断言或校验器的 format 插件 —— 另外别把格式检查和"这个邮箱真能收到信"混为一谈。
JSON Schema 和 TypeScript、OpenAPI 是一回事吗?
不是。TypeScript 的类型是 TypeScript 内部的编译期检查;OpenAPI 是用 JSON Schema 的一种方言来描述 HTTP 接口;而 JSON Schema 本身是一份 JSON 约定 —— 一种描述 JSON 数据结构的格式。
处理 JSON 的工具
- JSON Fix —— 在浏览器本地修复并格式化粘贴进来的 JSON。
- JSON 校验器 —— 检查严格 JSON 语法和解析器报的位置。
- JSON 查看器 —— 用可折叠的树查看嵌套 JSON。
- JSON Diff —— 比较两份 JSON 文档。
- JSON 与 YAML 对比 —— 为配置和数据交换挑对格式。
- JSON 转 TypeScript —— 把 JSON 样本变成 TypeScript 接口。
参考资料
- RFC 8259 —— IETF 的 JSON 数据交换标准。
- ECMA-404 —— Ecma International 的 JSON 数据交换语法。
- json.org —— Douglas Crockford 的 JSON 语法与概览。
- MDN:使用 JSON —— 面向浏览器的解析与序列化示例。
- JSON Schema 规范 —— 当前 Core 与 Validation 规范的入口。
- JSON Schema Draft 2020-12 —— 示例中声明使用的方言。
- Ajv schema language 文档 —— JavaScript 校验器的草案支持与构造函数。
- python-jsonschema 校验文档 —— Python 校验器类与 API。
最后校订于 2026 年 8 月。