什么是 JSON Schema 验证?
JSON Schema 验证是检查 JSON 文档是否符合 JSON Schema 中定义的一组结构和值约束的过程。Schema 本身是一个 JSON 文档,描述数据的预期结构:哪些属性是必填的、它们的类型要求、数字的允许范围、字符串模式、数组长度等。JSON Schema 规范由 json-schema.org 维护,并以 IETF 草案的形式发布,Draft 7 和 Draft 2020-12 是目前应用最广泛的版本。
普通 JSON 验证只检查语法(括号是否匹配?字符串是否加引号?),而 Schema 验证则更进一步。它回答如下问题:这个 API 的响应是否始终包含整数类型的 "id" 字段?"status" 字段是否属于三个允许值之一?嵌套对象的结构是否正确?这类结构验证能捕获语法检查完全漏掉的错误——因为语法合法的 JSON 对于你的应用来说仍可能是语义错误的。
JSON Schema 广泛用于 OpenAPI/Swagger 定义、配置文件验证、表单验证、数据库文档约束以及自动化测试。Ajv(JavaScript)、jsonschema(Python)和 check-jsonschema(CLI)等工具实现了该规范,使你可以通过编程方式验证数据。这个在线验证器让你无需安装任何库,只需粘贴 Schema 和数据文档,即可即时检查是否符合规范。
为什么使用在线 JSON Schema 验证器?
手动编写 Schema 并调试验证错误既耗时又繁琐。在线 JSON Schema 验证器能即时反馈数据是否符合 Schema,并通过清晰的错误信息精确指出失败的属性。
JSON Schema 验证的使用场景
JSON Schema 关键字参考
JSON Schema 由各类关键字构成,每个关键字对被验证的数据施加一项约束。下表列出了 Draft 7 及后续版本中最常用的关键字。同一 Schema 对象中可以组合使用多个关键字。
| 关键字 | 用途 | 示例 |
|---|---|---|
| type | Restricts the data type | "type": "string" |
| properties | Defines expected object keys and their schemas | "properties": { "name": { "type": "string" } } |
| required | Lists mandatory properties | "required": ["id", "name"] |
| items | Schema for array elements | "items": { "type": "number" } |
| enum | Restricts value to a fixed set | "enum": ["active", "inactive"] |
| pattern | Regex constraint on strings | "pattern": "^[A-Z]{2}\\d{4}$" |
| minimum / maximum | Numeric range bounds | "minimum": 0, "maximum": 100 |
| minLength / maxLength | String length bounds | "minLength": 1, "maxLength": 255 |
| $ref | Reuses another schema by URI | "$ref": "#/$defs/address" |
| additionalProperties | Controls extra keys in objects | "additionalProperties": false |
| anyOf / oneOf / allOf | Combines multiple schemas logically | "anyOf": [{ "type": "string" }, { "type": "null" }] |
| if / then / else | Conditional schema application | "if": { "properties": { "type": { "const": "email" } } } |
JSON Schema 草案对比:Draft 7 vs 2019-09 vs 2020-12
JSON Schema 经历了多个草案版本。Draft 7(2018 年发布)在工具链中拥有最广泛的支持。Draft 2019-09 引入了 $defs(替代 definitions)、unevaluatedProperties 和 $recursiveRef。Draft 2020-12(最新稳定版)将 $recursiveRef 替换为 $dynamicRef,并引入了 prefixItems 用于元组验证。选择草案版本时,请确认你的验证库是否支持。Ajv 支持全部三个草案;Python 的 jsonschema 库自 4.0 版起支持至 2020-12。
| 特性 | Draft 7 | Draft 2019-09 | Draft 2020-12 |
|---|---|---|---|
| $schema URI | draft-07/schema# | 2019-09/schema | 2020-12/schema |
| if / then / else | Yes | Yes | Yes |
| $defs (definitions) | definitions | $defs | $defs |
| $ref alongside keys | No (sibling ignored) | Yes | Yes |
| $dynamicRef | No | No ($recursiveRef) | Yes |
| prefixItems | No (use items array) | No (use items array) | Yes |
| unevaluatedProperties | No | Yes | Yes |
| $vocabulary | No | Yes | Yes |
代码示例
以下示例演示如何通过编程方式用各语言主流库对 JSON 进行 Schema 验证。
import Ajv from 'ajv';
const ajv = new Ajv();
const schema = {
type: 'object',
properties: {
name: { type: 'string', minLength: 1 },
age: { type: 'integer', minimum: 0 },
email: { type: 'string', format: 'email' }
},
required: ['name', 'email'],
additionalProperties: false
};
const data = { name: 'Alice', age: 30, email: 'alice@example.com' };
const validate = ajv.compile(schema);
const valid = validate(data);
console.log(valid); // → true
console.log(validate.errors); // → null
// Invalid data — missing required "email"
validate({ name: 'Bob', age: 25 });
console.log(validate.errors);
// → [{ instancePath: '', keyword: 'required', params: { missingProperty: 'email' } }]from jsonschema import validate, ValidationError
schema = {
"type": "object",
"properties": {
"name": {"type": "string", "minLength": 1},
"age": {"type": "integer", "minimum": 0},
"tags": {
"type": "array",
"items": {"type": "string"},
"uniqueItems": True
}
},
"required": ["name"]
}
# Valid data
validate(instance={"name": "Alice", "age": 30, "tags": ["admin"]}, schema=schema)
# → No exception raised
# Invalid data — wrong type for "age"
try:
validate(instance={"name": "Alice", "age": "thirty"}, schema=schema)
except ValidationError as e:
print(e.message)
# → 'thirty' is not of type 'integer'
print(e.json_path)
# → $.agepackage main
import (
"fmt"
"strings"
"github.com/santhosh-tekuri/jsonschema/v5"
)
func main() {
schemaJSON := `{
"type": "object",
"properties": {
"id": { "type": "integer" },
"status": { "enum": ["active", "inactive"] }
},
"required": ["id", "status"]
}`
compiler := jsonschema.NewCompiler()
compiler.AddResource("schema.json", strings.NewReader(schemaJSON))
schema, _ := compiler.Compile("schema.json")
// Valid data
data := map[string]interface{}{"id": 1, "status": "active"}
err := schema.Validate(data)
fmt.Println(err) // → <nil>
// Invalid — missing "status"
bad := map[string]interface{}{"id": 2}
err = schema.Validate(bad)
fmt.Println(err) // → validation failed: missing properties: 'status'
}# Install via pip pip install check-jsonschema # Validate a file against a schema check-jsonschema --schemafile schema.json data.json # → ok -- validation done # Validate against a remote schema (e.g., GitHub Actions workflow) check-jsonschema --builtin-schema vendor.github-workflows my-workflow.yml # Validate multiple files at once check-jsonschema --schemafile schema.json file1.json file2.json file3.json