validating-json-data
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseValidating JSON Data with z-schema
使用z-schema验证JSON数据
z-schema validates JSON data against JSON Schema (draft-04, draft-06, draft-07, draft-2019-09, draft-2020-12). Default draft: draft-2020-12.
z-schema可根据JSON Schema(draft-04、draft-06、draft-07、draft-2019-09、draft-2020-12版本)验证JSON数据。默认版本为draft-2020-12。
Quick start
快速开始
typescript
import ZSchema from 'z-schema';
const validator = ZSchema.create();
const schema = {
type: 'object',
properties: {
name: { type: 'string' },
age: { type: 'integer', minimum: 0 },
},
required: ['name'],
};
// Throws on invalid data
validator.validate({ name: 'Alice', age: 30 }, schema);Install:
npm install z-schematypescript
import ZSchema from 'z-schema';
const validator = ZSchema.create();
const schema = {
type: 'object',
properties: {
name: { type: 'string' },
age: { type: 'integer', minimum: 0 },
},
required: ['name'],
};
// 数据无效时抛出异常
validator.validate({ name: 'Alice', age: 30 }, schema);安装命令:
npm install z-schemaChoosing a validation mode
选择验证模式
z-schema has four modes based on two toggles: and . Pick the one that fits the use case.
asyncsafe| Mode | Factory call | Returns | Use when |
|---|---|---|---|
| Sync throw | | | Default — simple scripts and middleware |
| Sync safe | | | Need to inspect errors without try/catch |
| Async throw | | | Using async format validators |
| Async safe | | | Async + non-throwing |
z-schema基于和两个开关提供四种模式,可根据使用场景选择合适的模式。
asyncsafe| 模式 | 工厂调用方式 | 返回值 | 使用场景 |
|---|---|---|---|
| 同步抛出异常 | | | 默认模式——适用于简单脚本和中间件 |
| 同步安全模式 | | | 无需try/catch即可查看错误详情 |
| 异步抛出异常 | | | 使用异步格式验证器时需用此模式 |
| 异步安全模式 | | | 异步场景且无需抛出异常 |
Sync throw (default)
同步抛出异常(默认)
typescript
import ZSchema from 'z-schema';
const validator = ZSchema.create();
try {
validator.validate(data, schema);
} catch (err) {
// err is ValidateError
console.log(err.details); // SchemaErrorDetail[]
}typescript
import ZSchema from 'z-schema';
const validator = ZSchema.create();
try {
validator.validate(data, schema);
} catch (err) {
// err 是 ValidateError 实例
console.log(err.details); // SchemaErrorDetail[]
}Sync safe
同步安全模式
typescript
const validator = ZSchema.create({ safe: true });
const result = validator.validate(data, schema);
if (!result.valid) {
console.log(result.err?.details);
}Or call on a regular (throwing) validator for the same result shape:
.validateSafe()typescript
const validator = ZSchema.create();
const { valid, err } = validator.validateSafe(data, schema);typescript
const validator = ZSchema.create({ safe: true });
const result = validator.validate(data, schema);
if (!result.valid) {
console.log(result.err?.details);
}也可在常规(抛出异常的)验证器上调用方法,得到相同结构的返回结果:
.validateSafe()typescript
const validator = ZSchema.create();
const { valid, err } = validator.validateSafe(data, schema);Async throw
异步抛出异常
Required when using async format validators.
typescript
const validator = ZSchema.create({ async: true });
try {
await validator.validate(data, schema);
} catch (err) {
console.log(err.details);
}使用异步格式验证器时必须使用此模式。
typescript
const validator = ZSchema.create({ async: true });
try {
await validator.validate(data, schema);
} catch (err) {
console.log(err.details);
}Async safe
异步安全模式
typescript
const validator = ZSchema.create({ async: true, safe: true });
const { valid, err } = await validator.validate(data, schema);typescript
const validator = ZSchema.create({ async: true, safe: true });
const { valid, err } = await validator.validate(data, schema);Inspecting errors
查看错误详情
ValidateError.detailsSchemaErrorDetailtypescript
interface SchemaErrorDetail {
message: string; // "Expected type string but found type number"
code: string; // "INVALID_TYPE"
params: (string | number | Array<string | number>)[];
path: string | Array<string | number>; // "#/age" or ["age"]
keyword?: string; // "type", "required", "minLength", etc.
inner?: SchemaErrorDetail[]; // sub-errors from anyOf/oneOf/not
schemaPath?: Array<string | number>;
schemaId?: string;
}ValidateError.detailsSchemaErrorDetailtypescript
interface SchemaErrorDetail {
message: string; // "Expected type string but found type number"
code: string; // "INVALID_TYPE"
params: (string | number | Array<string | number>)[];
path: string | Array<string | number>; // "#/age" 或 ["age"]
keyword?: string; // "type", "required", "minLength" 等
inner?: SchemaErrorDetail[]; // 来自anyOf/oneOf/not的子错误
schemaPath?: Array<string | number>;
schemaId?: string;
}Example: walking nested errors
示例:遍历嵌套错误
Combinators (, , ) produce nested errors:
anyOfoneOfnotinnertypescript
const { valid, err } = validator.validateSafe(data, schema);
if (!valid && err) {
for (const detail of err.details) {
console.log(`${detail.path}: [${detail.code}] ${detail.message}`);
if (detail.inner) {
for (const sub of detail.inner) {
console.log(` └─ ${sub.path}: [${sub.code}] ${sub.message}`);
}
}
}
}组合器(、、)会产生嵌套的错误:
anyOfoneOfnotinnertypescript
const { valid, err } = validator.validateSafe(data, schema);
if (!valid && err) {
for (const detail of err.details) {
console.log(`${detail.path}: [${detail.code}] ${detail.message}`);
if (detail.inner) {
for (const sub of detail.inner) {
console.log(` └─ ${sub.path}: [${sub.code}] ${sub.message}`);
}
}
}
}Filtering errors
过滤错误
Pass as the third argument to include or exclude specific error codes:
ValidateOptionstypescript
// Only report type errors
validator.validate(data, schema, { includeErrors: ['INVALID_TYPE'] });
// Suppress string-length errors
validator.validate(data, schema, { excludeErrors: ['MIN_LENGTH', 'MAX_LENGTH'] });For the full error code list, see references/error-codes.md.
将作为第三个参数传入,可包含或排除特定错误代码:
ValidateOptionstypescript
// 仅报告类型错误
validator.validate(data, schema, { includeErrors: ['INVALID_TYPE'] });
// 屏蔽字符串长度相关错误
validator.validate(data, schema, { excludeErrors: ['MIN_LENGTH', 'MAX_LENGTH'] });完整的错误代码列表请参考 references/error-codes.md。
Schema pre-compilation
Schema预编译
Compile schemas at startup for better runtime performance and to resolve cross-references:
typescript
const validator = ZSchema.create();
const schemas = [
{
id: 'address',
type: 'object',
properties: { city: { type: 'string' }, zip: { type: 'string' } },
required: ['city'],
},
{
id: 'person',
type: 'object',
properties: {
name: { type: 'string' },
home: { $ref: 'address' },
},
required: ['name'],
},
];
// Compile all schemas (validates them and registers references)
validator.validateSchema(schemas);
// Validate data using a compiled schema ID
validator.validate({ name: 'Alice', home: { city: 'Paris' } }, 'person');在启动时编译Schema可提升运行时性能,并解析交叉引用:
typescript
const validator = ZSchema.create();
const schemas = [
{
id: 'address',
type: 'object',
properties: { city: { type: 'string' }, zip: { type: 'string' } },
required: ['city'],
},
{
id: 'person',
type: 'object',
properties: {
name: { type: 'string' },
home: { $ref: 'address' },
},
required: ['name'],
},
];
// 编译所有Schema(验证Schema并注册引用)
validator.validateSchema(schemas);
// 使用已编译的Schema ID验证数据
validator.validate({ name: 'Alice', home: { city: 'Paris' } }, 'person');Remote references
远程引用
Manual registration
手动注册
typescript
ZSchema.setRemoteReference('http://example.com/schemas/address.json', addressSchema);
// or per-instance:
validator.setRemoteReference('http://example.com/schemas/person.json', personSchema);typescript
ZSchema.setRemoteReference('http://example.com/schemas/address.json', addressSchema);
// 或针对单个实例:
validator.setRemoteReference('http://example.com/schemas/person.json', personSchema);Automatic loading via schema reader
通过Schema读取器自动加载
typescript
import fs from 'node:fs';
import path from 'node:path';
ZSchema.setSchemaReader((uri) => {
const filePath = path.resolve(__dirname, 'schemas', uri + '.json');
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
});typescript
import fs from 'node:fs';
import path from 'node:path';
ZSchema.setSchemaReader((uri) => {
const filePath = path.resolve(__dirname, 'schemas', uri + '.json');
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
});Diagnosing missing references
诊断缺失的引用
typescript
const { valid, err } = validator.validateSafe(data, schema);
if (!valid && err) {
const missing = validator.getMissingReferences(err);
const remote = validator.getMissingRemoteReferences(err);
}typescript
const { valid, err } = validator.validateSafe(data, schema);
if (!valid && err) {
const missing = validator.getMissingReferences(err);
const remote = validator.getMissingRemoteReferences(err);
}Custom format validators
自定义格式验证器
Global (shared across all validator instances)
全局(所有验证器实例共享)
typescript
ZSchema.registerFormat('postal-code', (value) => {
return typeof value === 'string' && /^\d{5}(-\d{4})?$/.test(value);
});typescript
ZSchema.registerFormat('postal-code', (value) => {
return typeof value === 'string' && /^\d{5}(-\d{4})?$/.test(value);
});Instance-scoped
实例作用域
typescript
const validator = ZSchema.create();
validator.registerFormat('postal-code', (value) => {
return typeof value === 'string' && /^\d{5}(-\d{4})?$/.test(value);
});typescript
const validator = ZSchema.create();
validator.registerFormat('postal-code', (value) => {
return typeof value === 'string' && /^\d{5}(-\d{4})?$/.test(value);
});Via options at creation time
创建时通过选项配置
typescript
const validator = ZSchema.create({
customFormats: {
'postal-code': (value) => typeof value === 'string' && /^\d{5}(-\d{4})?$/.test(value),
},
});typescript
const validator = ZSchema.create({
customFormats: {
'postal-code': (value) => typeof value === 'string' && /^\d{5}(-\d{4})?$/.test(value),
},
});Async format validators
异步格式验证器
Return . Requires .
Promise<boolean>{ async: true }typescript
const validator = ZSchema.create({ async: true });
validator.registerFormat('user-exists', async (value) => {
if (typeof value !== 'number') return false;
const user = await db.findUser(value);
return user != null;
});返回,需启用。
Promise<boolean>{ async: true }typescript
const validator = ZSchema.create({ async: true });
validator.registerFormat('user-exists', async (value) => {
if (typeof value !== 'number') return false;
const user = await db.findUser(value);
return user != null;
});Listing registered formats
列出已注册的格式
typescript
const formats = ZSchema.getRegisteredFormats();typescript
const formats = ZSchema.getRegisteredFormats();Choosing a draft version
选择draft版本
Set the draft explicitly if the schema targets a specific version:
typescript
const validator = ZSchema.create({ version: 'draft-07' });Valid values: , , , , (default), .
'draft-04''draft-06''draft-07''draft2019-09''draft2020-12''none'For a feature comparison across drafts, see references/draft-comparison.md.
如果Schema针对特定版本,可显式设置draft版本:
typescript
const validator = ZSchema.create({ version: 'draft-07' });有效值:、、、、(默认)、。
'draft-04''draft-06''draft-07''draft2019-09''draft2020-12''none'各draft版本的功能对比请参考 references/draft-comparison.md。
Common options
常用选项
| Option | Default | Purpose |
|---|---|---|
| | Stop validation at the first error |
| | Reject empty strings as type |
| | Reject empty arrays as type |
| | Enable all strict checks at once |
| | Suppress unknown format errors (modern drafts always ignore) |
| | |
| | Report error paths as arrays instead of JSON Pointer strings |
For the full options reference, see references/options.md.
| 选项名称 | 默认值 | 用途 |
|---|---|---|
| | 遇到第一个错误时停止验证 |
| | 拒绝将空字符串视为 |
| | 拒绝将空数组视为 |
| | 一次性启用所有严格检查 |
| | 屏蔽未知格式错误(现代draft版本默认忽略) |
| | |
| | 以数组形式返回错误路径,而非JSON Pointer字符串 |
完整的选项参考请见 references/options.md。
Validating sub-schemas
验证子Schema
Target a specific path within a schema:
typescript
validator.validate(carData, fullSchema, { schemaPath: 'definitions.car' });针对Schema中的特定路径进行验证:
typescript
validator.validate(carData, fullSchema, { schemaPath: 'definitions.car' });Browser usage (UMD)
浏览器使用(UMD)
html
<script src="node_modules/z-schema/umd/ZSchema.min.js"></script>
<script>
var validator = ZSchema.create();
try {
validator.validate({ name: 'test' }, { type: 'object' });
} catch (err) {
console.log(err.details);
}
</script>html
<script src="node_modules/z-schema/umd/ZSchema.min.js"></script>
<script>
var validator = ZSchema.create();
try {
validator.validate({ name: 'test' }, { type: 'object' });
} catch (err) {
console.log(err.details);
}
</script>TypeScript types
TypeScript类型
All types are exported from the package:
typescript
import type {
JsonSchema, // Schema type (all drafts union)
ZSchemaOptions, // Configuration options
ValidateOptions, // Per-call options (schemaPath, includeErrors, excludeErrors)
ValidateResponse, // { valid: boolean, err?: ValidateError }
SchemaErrorDetail, // Individual error detail
ErrorCode, // Error code string literal type
FormatValidatorFn, // (input: unknown) => boolean | Promise<boolean>
SchemaReader, // (uri: string) => JsonSchema
} from 'z-schema';
import { ValidateError } from 'z-schema';所有类型均从包中导出:
typescript
import type {
JsonSchema, // Schema类型(所有draft版本的联合类型)
ZSchemaOptions, // 配置选项
ValidateOptions, // 单次调用选项(schemaPath、includeErrors、excludeErrors)
ValidateResponse, // { valid: boolean, err?: ValidateError }
SchemaErrorDetail, // 单个错误详情
ErrorCode, // 错误代码字符串字面量类型
FormatValidatorFn, // (input: unknown) => boolean | Promise<boolean>
SchemaReader, // (uri: string) => JsonSchema
} from 'z-schema';
import { ValidateError } from 'z-schema';Reference files
参考文档
- references/error-codes.md — Full error code list with descriptions and examples
- references/options.md — Complete options reference with defaults
- references/draft-comparison.md — Feature comparison across JSON Schema drafts
- references/error-codes.md — 完整错误代码列表,含描述及示例
- references/options.md — 完整选项参考,含默认值
- references/draft-comparison.md — JSON Schema各draft版本的功能对比
Important conventions
重要约定
- Always use — never
ZSchema.create(options?). The factory returns the correctly typed variant.new ZSchema() - Error details are on (not
.details)..errors - Import types with and values with
import type { ... }.import { ValidateError } - Default draft is . Specify explicitly if targeting an older draft.
draft2020-12
- 始终使用——切勿使用
ZSchema.create(options?)。工厂函数会返回类型正确的实例。new ZSchema() - 错误详情在属性中(而非
.details)。.errors - 使用导入类型,使用
import type { ... }导入值。import { ValidateError } - 默认draft版本为。若针对旧版本draft,需显式指定。
draft2020-12