关于 writing-json-schemas
writing-json-schemas 是一项技能,帮助编写适用于 z-schema 验证的规范 JSON Schema。内容涵盖结构、约束、组合、引用和不同草案的实践,默认面向 draft-2020-12。
主要功能
- 01draft-2020-12 架构模板
- 02对象与数组约束
- 03组合器和条件架构
- 04可复用定义与引用
- 05严格属性设置指南
适用场景
- 01为应用数据定义架构
- 02使用 allOf 和 $defs 组合架构
- 03选择 draft-2020-12 的元组语法
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ zaggino/ z-schema --skill writing-json-schemas安装后在 Claude Code 中输入/writing-json-schemas确认已加载。
详细介绍
为 z-schema 编写 JSON Schema
编写正确、符合惯例且能通过 z-schema 验证的 JSON Schema。默认目标:draft-2020-12。
Schema 模板
每个 Schema 都以 $schema 声明和 type 开头:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {},
"required": [],
"additionalProperties": false
}
当需要拒绝额外属性时,显式设置 additionalProperties: false——z-schema 默认允许额外属性。
对象 Schema
包含必填字段的基本对象
{
"type": "object",
"properties": {
"name": { "type": "string", "minLength": 1 },
"email": { "type": "string", "format": "email" },
"age": { "type": "integer", "minimum": 0, "maximum": 150 }
},
"required": ["name", "email"],
"additionalProperties": false
}
嵌套对象
{
"type": "object",
"properties": {
"address": {
"type": "object",
"properties": {
"street": { "type": "string" },
"city": { "type": "string" },
"zip": { "type": "string", "pattern": "^\\d{5}(-\\d{4})?$" }
},
"required": ["street", "city"]
}
}
}
动态属性名称
使用 patternProperties 通过正则表达式验证属性键:
{
"type": "object",
"patternProperties": {
"^x-": { "type": "string" }
},
"additionalProperties": false
}
使用 propertyNames(draft-06+)约束所有属性键字符串:
{
"type": "object",
"propertyNames": { "pattern": "^[a-z_]+$" }
}
数组 Schema
统一类型的数组
{
"type": "array",
"items": { "type": "string" },
"minItems": 1,
"uniqueItems": true
}
元组验证(draft-2020-12)
对位置固定的类型使用 prefixItems,对剩余元素使用 items:
{
"type": "array",
"prefixItems": [{ "type": "string" }, { "type": "integer" }],
"items": false
}
items: false 会拒绝超出元组位置的额外元素。
Contains(draft-06+)
要求至少有一个匹配项:
{
"type": "array",
"contains": { "type": "string", "const": "admin" }
}
使用计数约束(draft-2019-09+):
{
"type": "array",
"contains": { "type": "integer", "minimum": 10 },
"minContains": 2,
"maxContains": 5
}
字符串约束
{
"type": "string",
"minLength": 1,
"maxLength": 255,
"pattern": "^[A-Za-z0-9_]+$"
}
格式验证
z-schema 内置了以下格式验证器:date、date-time、time、email、idn-email、hostname、idn-hostname、ipv4、ipv6、uri、uri-reference、uri-template、iri、iri-reference、json-pointer、relative-json-pointer、regex、duration、uuid。
{ "type": "string", "format": "date-time" }
默认始终启用格式断言(formatAssertions: null)。在 draft-2020-12 中,如需使用感知词汇的行为,请在验证器上设置 formatAssertions: true。
数值约束
{
"type": "number",
"minimum": 0,
"maximum": 100,
"multipleOf": 0.01
}
使用 exclusiveMinimum / exclusiveMaximum 设置严格边界:
{ "type": "integer", "exclusiveMinimum": 0, "exclusiveMaximum": 100 }
组合器
anyOf — 至少匹配一个
{
"anyOf": [{ "type": "string" }, { "type": "number" }]
}
oneOf — 恰好匹配一个
{
"oneOf": [
{ "type": "string", "maxLength": 5 },
{ "type": "string", "minLength": 10 }
]
}
allOf — 全部匹配
用于组合 Schema。将基础 Schema 与细化规则组合:
{
"allOf": [{ "$ref": "#/$defs/base" }, { "properties": { "extra": { "type": "string" } } }]
}
not — 不得匹配
{ "not": { "type": "null" } }
if / then / else(draft-07+)
条件验证——当逻辑为“如果满足 X,则要求 Y”时,优先使用它,而不是复杂的 oneOf:
{
"type": "object",
"properties": {
"type": { "type": "string", "enum": ["personal", "business"] },
"company": { "type": "string" }
},
"if": { "properties": { "type": { "const": "business" } } },
"then": { "required": ["company"] },
"else": {}
}
如何选择组合器
| 场景 | 使用 |
|---|---|
| 值可以是多种类型 | anyOf |
| 必须恰好匹配一个变体 | oneOf |
| 组合继承的 Schema | allOf |
| “如果满足条件,则要求字段” | if/then/else |
| 排除特定结构 | not |
当条件是单个判别字段时,优先使用 if/then/else,而不是 oneOf——这样会生成更清晰的错误消息。
使用 $ref 和 $defs 复用 Schema
本地定义
{
"$defs": {
"address": {
"type": "object",
"properties": {
"street": { "type": "string" },
"city": { "type": "string" }
},
"required": ["street", "city"]
}
},
"type": "object",
"properties": {
"home": { "$ref": "#/$defs/address" },
"work": { "$ref": "#/$defs/address" }
}
}
跨 Schema 引用
编译一个 Schema 数组,并通过 ID 引用:
import ZSchema from 'z-schema';
const schemas = [
{
$id: 'address',
type: 'object',
properties: { city: { type: 'string' } },
required: ['city'],
},
{
$id: 'person',
type: 'object',
properties: {
name: { type: 'string' },
home: { $ref: 'address' },
},
required: ['name'],
},
];
const validator = ZSchema.create();
validator.validateSchema(schemas);
validator.validate({ name: 'Alice', home: { city: 'Paris' } }, 'person');
使用 unevaluatedProperties 编写严格 Schema(draft-2019-09+)
使用 allOf 组合 Schema 时,子 Schema 中的 additionalProperties: false 会阻止兄弟 Schema 中定义的属性。改用 unevaluatedProperties——它会追踪所有应用器已评估的属性:
{
"allOf": [
{
"type": "object",
"properties": { "name": { "type": "string" } },
"required": ["name"]
},
{
"type": "object",
"properties": { "age": { "type": "integer" } }
}
],
"unevaluatedProperties": false
}
这会接受 { "name": "Alice", "age": 30 },但拒绝 { "name": "Alice", "age": 30, "extra": true }。
验证 Schema 本身
始终在启动时验证 Schema:
const validator = ZSchema.create();
try {
validator.validateSchema(schema);
} catch (err) {
console.log('Schema errors:', err.details);
}
常见错误
- 忘记设置
additionalProperties:默认情况下允许额外属性。设置additionalProperties: false或使用unevaluatedProperties: false来拒绝它们。 - 在
allOf中使用additionalProperties: false:这会阻止兄弟 Schema 中的属性。请改为在顶层设置unevaluatedProperties: false(draft-2019-09+)。 - draft-2020-12 中数组的
items:元组验证请使用prefixItems。现在items表示“剩余元素的 Schema”。 - 缺少
$schema:如果没有它,z-schema 会使用配置的默认草案。请包含$schema,以明确指定目标草案。 definitions与$defs:两者都可用,但$defs是 draft-2019-09+ 中的规范形式。请保持一致。