更新时间: 2025-12-25
const { dsl } = require('schema-dsl');
// 基本类型
const schema = dsl({
name: 'string!', // 必填字符串
age: 'number', // 可选数字
email: 'email!', // 必填邮箱
active: 'boolean', // 布尔值
tags: 'array<string>' // 字符串数组
});| 类型 | DSL | 说明 |
|---|---|---|
| 字符串 | string |
文本类型 |
| 数字 | number |
浮点数 |
| 整数 | integer |
整数 |
| 布尔 | boolean |
true/false |
| 对象 | object |
嵌套对象 |
| 数组 | array |
数组类型 |
| 空值 | null |
null值 |
| 任意 | any |
任意类型 |
| 类型 | DSL | 说明 |
|---|---|---|
| 邮箱 | email |
邮箱地址 |
| URL | url |
网址 |
| UUID | uuid |
UUID格式 |
| 日期 | date |
YYYY-MM-DD |
| 日期时间 | datetime |
ISO 8601 |
| 时间 | time |
HH:mm:ss |
| IPv4 | ipv4 |
IPv4地址 |
| IPv6 | ipv6 |
IPv6地址 |
| 二进制 | binary |
Base64编码 |
// 基本类型
'string' // 字符串
'number' // 数字
'integer' // 整数
'boolean' // 布尔
// 格式类型
'email' // 邮箱
'url' // URL
'date' // 日期
'uuid' // UUID使用 ! 标记必填字段,使用 ? 显式标记可选字段:
const schema = dsl({
username: 'string!', // 必填
nickname: 'string', // 可选(默认)
bio: 'string?', // 显式可选(等价于 string)
email: 'email?' // 可选邮箱
});说明:
!- 必填标记,字段不能为空?- 可选标记,字段可以为空(默认行为)- 不加标记 - 默认可选
推荐:
- 使用
!明确标记必填字段 - 使用
?在需要明确表达"可选"时增强代码可读性
支持两种方式:
// 方式1: 字段内部必填
const schema1 = dsl({
user: {
name: 'string!', // name 必填(user 可选)
email: 'email!' // email 必填
}
});
// 方式2: 对象本身必填 ✅ 推荐
const schema2 = dsl({
'user!': { // user 本身必填
name: 'string', // name 可选
email: 'email' // email 可选
}
});'string:10' // 最大长度10
'string:-10' // 最大长度10(明确语法)
'string:3-32' // 长度3-32
'string:10-' // 最小长度10示例:
const schema = dsl({
username: 'string:3-32!', // 3-32字符,必填
bio: 'string:500', // 最大500字符
password: 'string:8-' // 最少8字符
});'number:100' // 最大值100
'number:0-100' // 范围0-100
'number:18-' // 最小值18示例:
const schema = dsl({
age: 'number:18-120', // 18-120
score: 'number:100', // 0-100
price: 'number:0-' // ≥0
});使用 | 分隔枚举值:
const schema = dsl({
status: 'active|inactive|pending',
gender: 'male|female|other!',
role: 'admin|user|guest'
});支持特定格式的约束:
'phone:cn' // 中国手机号
'idCard:cn' // 中国身份证
'creditCard:visa' // Visa信用卡
'licensePlate:cn' // 中国车牌
'postalCode:cn' // 中国邮编
'passport:cn' // 中国护照示例:
const schema = dsl({
mobile: 'phone:cn!',
id: 'idCard:cn',
card: 'creditCard:mastercard'
});'array' // 任意类型数组
'array<string>' // 字符串数组
'array<number>' // 数字数组
'array<integer>' // 整数数组'array:1-10' // 1-10个元素
'array!1-10' // 1-10个元素,必填
'array:1-' // 至少1个元素
'array:-10' // 最多10个元素
'array:1-10<string>' // 1-10个字符串元素示例:
const schema = dsl({
tags: 'array!1-10<string>', // 必填,1-10个字符串
scores: 'array:1-5<number>', // 可选,1-5个数字
items: 'array:1-<string>' // 至少1个字符串
});const schema = dsl({
tags: 'array<string:1-20>', // 每个字符串1-20字符
scores: 'array<number:0-100>', // 每个数字0-100
ids: 'array<integer:1->' // 每个整数≥1
});// 二维数组
const schema = dsl({
matrix: 'array<array<number>>'
});
// 对象数组
const schema = dsl({
users: 'array<object>',
// 或更详细定义
items: {
type: 'array',
items: {
name: 'string!',
age: 'number'
}
}
});const schema = dsl({
user: {
name: 'string!',
email: 'email!',
age: 'number'
}
});const schema = dsl({
user: {
profile: {
bio: 'string:500',
social: {
twitter: 'url',
github: 'url'
}
}
}
});const schema = dsl({
'user!': { // user 必填
name: 'string!', // name 必填
contacts: 'array!1-5<object>', // 1-5个联系方式
tags: 'array<string:1-20>' // 字符串数组
}
});支持更优雅的条件验证语法 dsl.match 和 dsl.if。
类似于 switch-case,根据某个字段的值决定当前字段的验证规则。
语法:
dsl.match(field, {
value1: 'schema1',
value2: 'schema2',
_default: 'defaultSchema' // 可选
})示例:
const schema = dsl({
contactType: 'email|phone',
// 根据 contactType 的值决定 contact 的规则
contact: dsl.match('contactType', {
email: 'email!', // contactType=email 时
phone: 'string:11!', // contactType=phone 时
_default: 'string' // 其他情况
})
});处理非英文值: 如果条件值包含中文、数字或特殊字符,给键名加上引号即可:
discount: dsl.match('level', {
'普通用户': 'number:0-5',
'VIP-1': 'number:0-20',
'100': 'number:0-50'
})适用于简单的二选一场景。
语法:
dsl.if(conditionField, thenSchema, elseSchema)示例:
const schema = dsl({
isVip: 'boolean',
// 如果是VIP,折扣0-50,否则0-10
discount: dsl.if('isVip', 'number:0-50', 'number:0-10')
});const schema = dsl({
username: 'string:3-32!'
.pattern(/^[a-zA-Z0-9_]+$/)
.label('用户名')
.messages({
'pattern': '只能包含字母、数字和下划线'
}),
email: 'email!'
.label('邮箱地址')
.description('用于登录和接收通知')
.custom(async (value) => {
const exists = await checkEmailExists(value);
if (exists) return '邮箱已被占用';
})
});const schema = dsl({
username: 'string!'.username('5-20'), // 自动正则+长度
phone: 'string!'.phone('cn'), // 中国手机号
password: 'string!'.password('strong') // 强密码
});'string | number' // ❌ 不支持解决方案: 使用 dsl.match (推荐)
// ✅ 推荐:使用 dsl.match
const schema = dsl({
vipLevel: 'string',
discount: dsl.match('vipLevel', {
gold: 'number:0-50',
silver: 'number:0-20',
normal: 'number:0-5'
})
});✅ 推荐: 使用简洁的 DSL 语法
'array!1-10<string:1-20>' // 1-10个元素,每个1-20字符{
type: 'array',
items: { type: 'string' },
minItems: 1,
maxItems: 10
}'string:/^[a-z]+$/' // ❌ 不支持解决方案: 使用 .pattern() 方法
'string!'.pattern(/^[a-z]+$/) // ✅ 推荐'string!@custom' // ❌ 不支持解决方案: 使用 .custom() 方法
'string!'.custom(async (value) => {
// 自定义逻辑
if (await checkExists(value)) {
return '已存在';
}
})'array<object{name:string,age:number}>' // ❌ 不支持解决方案: 使用完整对象定义
const schema = dsl({
users: {
type: 'array',
items: {
name: 'string!',
age: 'number:18-'
}
}
});const { dsl } = require('schema-dsl');
const schema = dsl({
// 基本信息
username: 'string:3-32!'.username().label('用户名'),
password: 'string!'.password('strong').label('密码'),
email: 'email!'.label('邮箱'),
phone: 'string!'.phone('cn').label('手机号'),
// 个人资料
'profile!': {
realName: 'string:2-50',
gender: 'male|female|other',
birthday: 'date',
bio: 'string:500'
},
// 地址信息
addresses: 'array:1-5<object>', // 1-5个地址
// 标签
tags: 'array:1-10<string:1-20>', // 1-10个标签,每个1-20字符
// 同意条款
agree: 'boolean!'
});const schema = dsl({
// 商品基本信息
title: 'string:1-100!',
price: 'number:0-!',
stock: 'integer:0-',
status: 'on_sale|off_sale|sold_out!',
// 商品详情
'details!': {
description: 'string:10000',
images: 'array!1-10<url>',
specs: 'array<object>',
tags: 'array:1-20<string:1-30>'
},
// SKU信息
skus: {
type: 'array',
minItems: 1,
items: {
sku_code: 'string!',
price: 'number!',
stock: 'integer!'
}
}
});const schema = dsl({
// 查询参数
page: 'integer:1-',
pageSize: 'integer:10-100',
keyword: 'string:1-50',
// 筛选条件
filters: {
category: 'array<string>',
priceRange: {
min: 'number:0-',
max: 'number:0-'
},
status: 'active|inactive'
},
// 排序
sort: {
field: 'price|created_at|sales',
order: 'asc|desc'
}
});A: 为了降低学习成本和减少歧义。使用完整类型名更清晰,特别是对新手更友好。
A: 支持直接在DSL中写:
'array!1-10<string>' // 推荐A: 使用完整对象定义:
const schema = dsl({
users: {
type: 'array',
items: {
name: 'string!',
email: 'email!'
}
}
});A: 支持。推荐使用 dsl.match:
dsl.match('vipLevel', { gold: 'number:0-50', silver: 'number:0-20' })A: 能,使用 .pattern() 方法:
'string!'.pattern(/^[a-z]+$/)最后更新: 2025-12-29
作者: SchemaI-DSL Team