schema-dsl 2.0.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (145) hide show
  1. package/CHANGELOG.md +130 -113
  2. package/LICENSE +21 -21
  3. package/README.md +628 -628
  4. package/dist/{DslBuilder-DkLaOo9Q.d.ts → DslBuilder-BIgQOAXp.d.ts} +2 -0
  5. package/dist/{DslBuilder-DQDN0ZxZ.d.cts → DslBuilder-CjHTucNQ.d.cts} +2 -0
  6. package/dist/{Validator-hFWKGxir.d.ts → Validator-CllRdrY0.d.ts} +1 -1
  7. package/dist/{Validator-C7GsVQOH.d.cts → Validator-D6okG9tr.d.cts} +1 -1
  8. package/dist/index.cjs +75 -29
  9. package/dist/index.d.cts +10 -4
  10. package/dist/index.d.ts +10 -4
  11. package/dist/index.js +75 -29
  12. package/dist/plugins/custom-format.cjs +33 -17
  13. package/dist/plugins/custom-format.d.cts +1 -1
  14. package/dist/plugins/custom-format.d.ts +1 -1
  15. package/dist/plugins/custom-format.js +33 -17
  16. package/dist/plugins/custom-type-example.cjs +33 -17
  17. package/dist/plugins/custom-type-example.d.cts +1 -1
  18. package/dist/plugins/custom-type-example.d.ts +1 -1
  19. package/dist/plugins/custom-type-example.js +33 -17
  20. package/dist/plugins/custom-validator.cjs +0 -2
  21. package/dist/plugins/custom-validator.d.cts +1 -1
  22. package/dist/plugins/custom-validator.d.ts +1 -1
  23. package/dist/plugins/custom-validator.js +0 -2
  24. package/docs/FEATURE-INDEX.md +553 -553
  25. package/docs/add-custom-locale.md +496 -496
  26. package/docs/add-keyword.md +24 -24
  27. package/docs/api-reference.md +1047 -1047
  28. package/docs/api.md +13 -13
  29. package/docs/best-practices-project-structure.md +417 -417
  30. package/docs/best-practices.md +712 -712
  31. package/docs/cache-manager.md +344 -344
  32. package/docs/compile.md +45 -45
  33. package/docs/conditional-api.md +1307 -1307
  34. package/docs/custom-extensions-guide.md +339 -339
  35. package/docs/design-philosophy.md +606 -606
  36. package/docs/doc-index.md +324 -324
  37. package/docs/dsl-syntax.md +714 -714
  38. package/docs/dynamic-locale.md +608 -608
  39. package/docs/enum.md +482 -482
  40. package/docs/error-handling.md +1975 -1975
  41. package/docs/export-guide.md +501 -501
  42. package/docs/export-limitations.md +567 -567
  43. package/docs/faq.md +596 -596
  44. package/docs/frontend-i18n-guide.md +307 -307
  45. package/docs/i18n-user-guide.md +487 -487
  46. package/docs/i18n.md +476 -476
  47. package/docs/index.md +48 -48
  48. package/docs/json-schema-basics.md +40 -40
  49. package/docs/label-vs-description.md +271 -271
  50. package/docs/markdown-exporter.md +406 -406
  51. package/docs/mongodb-exporter.md +302 -302
  52. package/docs/multi-language.md +26 -26
  53. package/docs/multi-type-support.md +322 -322
  54. package/docs/mysql-exporter.md +280 -280
  55. package/docs/number-operators.md +449 -449
  56. package/docs/optional-marker-guide.md +326 -326
  57. package/docs/performance-guide.md +49 -49
  58. package/docs/plugin-system.md +381 -381
  59. package/docs/plugin-type-registration.md +34 -34
  60. package/docs/postgresql-exporter.md +311 -311
  61. package/docs/public/favicon.svg +4 -4
  62. package/docs/quick-start.md +435 -435
  63. package/docs/runtime-locale-support.md +532 -532
  64. package/docs/schema-helper.md +345 -345
  65. package/docs/schema-utils-advanced-issues.md +23 -23
  66. package/docs/schema-utils-best-practices.md +20 -20
  67. package/docs/schema-utils-chaining.md +150 -150
  68. package/docs/schema-utils.md +524 -524
  69. package/docs/security-checklist.md +20 -20
  70. package/docs/string-extensions.md +488 -488
  71. package/docs/troubleshooting.md +486 -486
  72. package/docs/type-converter.md +310 -310
  73. package/docs/type-reference.md +242 -242
  74. package/docs/typescript-guide.md +584 -584
  75. package/docs/union-type-guide.md +157 -157
  76. package/docs/union-types.md +284 -284
  77. package/docs/validate-async.md +491 -491
  78. package/docs/validate-batch.md +49 -49
  79. package/docs/validate-dsl-object-support.md +578 -578
  80. package/docs/validate.md +506 -506
  81. package/docs/validation-guide.md +502 -502
  82. package/docs/validator.md +39 -39
  83. package/package.json +131 -131
  84. package/plugins/custom-format.cjs +8 -8
  85. package/plugins/custom-type-example.cjs +8 -8
  86. package/plugins/custom-validator.cjs +8 -8
  87. package/src/adapters/DslAdapter.ts +111 -111
  88. package/src/adapters/index.ts +1 -1
  89. package/src/config/constants.ts +83 -83
  90. package/src/config/index.ts +2 -2
  91. package/src/config/patterns.ts +77 -77
  92. package/src/core/CacheManager.ts +169 -159
  93. package/src/core/ConditionalBuilder.ts +382 -382
  94. package/src/core/ConditionalRuntime.ts +27 -27
  95. package/src/core/ConditionalValidator.ts +254 -254
  96. package/src/core/DslBuilder.ts +687 -677
  97. package/src/core/ErrorCodes.ts +38 -38
  98. package/src/core/ErrorFormatter.ts +271 -271
  99. package/src/core/JSONSchemaCore.ts +65 -65
  100. package/src/core/Locale.ts +187 -187
  101. package/src/core/MessageTemplate.ts +42 -42
  102. package/src/core/ObjectDslBuilder.ts +64 -64
  103. package/src/core/PluginManager.ts +326 -326
  104. package/src/core/StringExtensions.ts +140 -140
  105. package/src/core/TemplateEngine.ts +44 -44
  106. package/src/core/Validator.ts +448 -448
  107. package/src/errors/I18nError.ts +159 -159
  108. package/src/errors/ValidationError.ts +105 -105
  109. package/src/exporters/BaseExporter.ts +60 -60
  110. package/src/exporters/MarkdownExporter.ts +305 -305
  111. package/src/exporters/MongoDBExporter.ts +126 -126
  112. package/src/exporters/MySQLExporter.ts +156 -155
  113. package/src/exporters/PostgreSQLExporter.ts +222 -222
  114. package/src/exporters/index.ts +18 -18
  115. package/src/index.ts +651 -633
  116. package/src/locales/en-US.ts +160 -160
  117. package/src/locales/es-ES.ts +160 -160
  118. package/src/locales/fr-FR.ts +160 -160
  119. package/src/locales/index.ts +103 -103
  120. package/src/locales/ja-JP.ts +160 -160
  121. package/src/locales/types.ts +156 -156
  122. package/src/locales/zh-CN.ts +160 -160
  123. package/src/parser/ConstraintParser.ts +101 -101
  124. package/src/parser/DslParser.ts +470 -470
  125. package/src/parser/SchemaCompiler.ts +66 -66
  126. package/src/parser/TypeRegistry.ts +250 -250
  127. package/src/parser/index.ts +6 -6
  128. package/src/plugins/custom-format.ts +124 -126
  129. package/src/plugins/custom-type-example.ts +106 -108
  130. package/src/plugins/custom-validator.ts +138 -140
  131. package/src/types/conditional.ts +28 -28
  132. package/src/types/config.ts +59 -59
  133. package/src/types/dsl.ts +131 -131
  134. package/src/types/error.ts +60 -60
  135. package/src/types/index.ts +17 -17
  136. package/src/types/infer.ts +127 -127
  137. package/src/types/plugin.ts +58 -58
  138. package/src/types/safe-regex.d.ts +9 -9
  139. package/src/types/schema.ts +66 -66
  140. package/src/types/validate.ts +71 -71
  141. package/src/utils/SchemaHelper.ts +196 -196
  142. package/src/utils/SchemaUtils.ts +365 -346
  143. package/src/utils/TypeConverter.ts +215 -215
  144. package/src/utils/index.ts +10 -10
  145. package/src/validators/CustomKeywords.ts +477 -477
package/docs/validate.md CHANGED
@@ -1,506 +1,506 @@
1
- # validate 方法详细文档
2
-
3
- ## 📑 目录
4
-
5
- ### 基础概念
6
- - [概述](#概述) - validate 方法介绍
7
- - [方法签名](#方法签名) - API 定义
8
-
9
- ### 参数详解
10
- - [参数详解](#参数详解)
11
- - [schema 参数](#schema-参数)
12
- - [options 对象属性](#options-对象属性)
13
- - [返回值详解](#返回值详解)
14
- - [valid (Boolean)](#valid-boolean)
15
- - [errors (Array)](#errors-array)
16
- - [data (Any)](#data-any)
17
-
18
- ### 使用示例
19
- - [基础示例](#基础示例)
20
- - [示例 1: 验证简单对象](#示例-1-验证简单对象)
21
- - [示例 2: 验证复杂对象](#示例-2-验证复杂对象)
22
- - [示例 3: 处理验证错误](#示例-3-处理验证错误)
23
- - [示例 4: 使用默认值](#示例-4-使用默认值)
24
-
25
- ### 高级功能
26
- - [高级用法](#高级用法)
27
- - [批量验证](#批量验证)
28
- - [自定义错误格式](#自定义错误格式)
29
- - [性能优化](#性能优化)
30
-
31
- ### 参考资料
32
- - [相关文档](#相关文档)
33
- - [API 参考](#api-参考)
34
-
35
- ---
36
-
37
- ## 概述
38
-
39
- `validate` 是 Validator 类的核心方法,用于验证数据是否符合 JSON Schema 定义。基于高性能的 ajv 验证器实现。
40
-
41
- ---
42
-
43
- ## 方法签名
44
-
45
- ```javascript
46
- validator.validate(schema, data, options = {})
47
- ```
48
-
49
- **参数说明**:
50
- - `schema` (Object|Function): JSON Schema 对象或已编译的验证函数
51
- - `data` (Any): 待验证的数据
52
- - `options` (Object): 验证选项(可选)
53
-
54
- **返回值**:
55
- ```javascript
56
- {
57
- valid: Boolean, // 是否有效
58
- errors: Array, // 成功时为空数组,失败时为错误列表
59
- data: Any // 当前实现会返回本次验证数据(可能被 useDefaults 修改)
60
- }
61
- ```
62
-
63
- 当前实现中,`data` 与 `errors` 都会随结果一并返回:成功时 `errors` 为空数组,验证失败时仍会保留 `data` 以便排查输入。
64
-
65
- ---
66
-
67
- ## 参数详解
68
-
69
- ### schema 参数
70
-
71
- JSON Schema 对象,支持 JSON Schema Draft 7 标准。
72
-
73
- | 参数类型 | 说明 | 来源 |
74
- |---------|------|------|
75
- | Object | JSON Schema 对象 | JSON Schema 标准 ✅ |
76
- | Function | 已编译的验证函数(通过 `compile()` 生成) | ajv ✅ |
77
-
78
- ### options 对象属性
79
-
80
- `validator.validate(schema, data, options)` 当前按本次调用实际读取以下参数:
81
-
82
- | 参数 | 类型 | 必填 | 默认值 | 说明 |
83
- |------|------|------|--------|------|
84
- | `format` | Boolean | 否 | `true` | 是否格式化错误信息 |
85
- | `locale` | String | 否 | — | 动态指定语言,如 `'zh-CN'`、`'en-US'`、`'ja-JP'` |
86
- | `messages` | Object | 否 | — | 自定义错误消息覆盖 |
87
-
88
- ### 相关配置入口
89
-
90
- 以下能力**不属于** `validator.validate(schema, data, options)` 的逐次调用参数:
91
-
92
- | 能力 | 正确入口 | 说明 |
93
- |------|----------|------|
94
- | `allErrors` / `useDefaults` / `coerceTypes` / `removeAdditional` / `cache` | `new Validator(options)` | 这些配置在创建 `Validator` 实例时注入到底层 AJV / 缓存层 |
95
- | `strict` | Schema 本身 | 如果需要禁止额外字段,请在 schema 层使用 `DslBuilder.strict()` 或等价的 schema 级约束 |
96
- | `coerce` | 顶层 `validate()` / `validateAsync()` 便捷函数 | 顶层 helper 默认会做字符串 → 数字 / 布尔值的便捷转换,传 `{ coerce: false }` 可关闭 |
97
-
98
- 如果你需要在**单次调用**中覆盖错误输出,请使用上表中的 `format`、`locale`、`messages`;如果你需要调整验证器行为,请优先在 `Validator` 构造阶段配置。
99
-
100
- ---
101
-
102
- ## 返回值详解
103
-
104
- ### valid (Boolean)
105
-
106
- 表示数据是否通过验证。
107
-
108
- ```javascript
109
- result.valid === true // 验证通过
110
- result.valid === false // 验证失败
111
- ```
112
-
113
- ### errors (Array)
114
-
115
- 验证错误列表。当前实现成功时返回空数组,验证失败时包含详细错误信息。
116
-
117
- **错误对象结构**:
118
- ```javascript
119
- {
120
- path: String, // 错误字段路径,如 'user.email'
121
- message: String, // 错误描述信息
122
- keyword: String, // 触发的 Schema 关键字
123
- params: Object // 错误相关参数
124
- }
125
- ```
126
-
127
- ### data (Any)
128
-
129
- 验证后的数据。当前实现即使在验证失败时也会保留本次验证数据,便于排查输入;如果 Validator 配置了 `useDefaults: true`,则也可能反映 Schema 中应用后的默认值。
130
-
131
- ---
132
-
133
- ## 基础示例
134
-
135
- ### 示例 1: 验证简单对象
136
-
137
- ```javascript
138
- const { Validator } = require('schema-dsl');
139
-
140
- const validator = new Validator();
141
-
142
- const schema = {
143
- type: 'object',
144
- properties: {
145
- name: { type: 'string' },
146
- age: { type: 'number' }
147
- },
148
- required: ['name']
149
- };
150
-
151
- const result = validator.validate(schema, {
152
- name: 'John',
153
- age: 25
154
- });
155
-
156
- console.log(result.valid); // true
157
- console.log(result.errors); // []
158
- ```
159
-
160
- ### 示例 2: 处理验证失败
161
-
162
- ```javascript
163
- const result = validator.validate(schema, {
164
- age: 'invalid'
165
- });
166
-
167
- console.log(result.valid); // false
168
- console.log(result.errors);
169
- // 当前实现返回格式化后的错误列表:
170
- // [
171
- // { path: 'name', message: 'name不能为空' },
172
- // { path: 'age', message: 'age应该是 number 类型' }
173
- // ]
174
- ```
175
-
176
- ---
177
-
178
- ## 高级示例
179
-
180
- ### 示例 3: 验证字符串约束
181
-
182
- ```javascript
183
- const schema = {
184
- type: 'string',
185
- minLength: 3,
186
- maxLength: 32,
187
- pattern: '^[a-zA-Z0-9]+$'
188
- };
189
-
190
- // 有效数据
191
- console.log(validator.validate(schema, 'john123').valid); // true
192
-
193
- // 太短
194
- console.log(validator.validate(schema, 'ab').valid); // false
195
-
196
- // 包含非法字符
197
- console.log(validator.validate(schema, 'john-123').valid); // false
198
- ```
199
-
200
- ### 示例 4: 验证数字范围
201
-
202
- ```javascript
203
- const schema = {
204
- type: 'number',
205
- minimum: 0,
206
- maximum: 100
207
- };
208
-
209
- console.log(validator.validate(schema, 50).valid); // true
210
- console.log(validator.validate(schema, -1).valid); // false
211
- console.log(validator.validate(schema, 101).valid); // false
212
- ```
213
-
214
- ### 示例 5: 验证邮箱格式
215
-
216
- ```javascript
217
- const schema = {
218
- type: 'string',
219
- format: 'email'
220
- };
221
-
222
- console.log(validator.validate(schema, 'test@example.com').valid); // true
223
- console.log(validator.validate(schema, 'invalid-email').valid); // false
224
- ```
225
-
226
- ### 示例 6: 验证枚举值
227
-
228
- ```javascript
229
- const schema = {
230
- type: 'string',
231
- enum: ['active', 'inactive', 'pending']
232
- };
233
-
234
- console.log(validator.validate(schema, 'active').valid); // true
235
- console.log(validator.validate(schema, 'invalid').valid); // false
236
- ```
237
-
238
- ### 示例 7: 验证嵌套对象
239
-
240
- ```javascript
241
- const schema = {
242
- type: 'object',
243
- properties: {
244
- user: {
245
- type: 'object',
246
- properties: {
247
- name: { type: 'string' },
248
- email: { type: 'string', format: 'email' }
249
- },
250
- required: ['name', 'email']
251
- }
252
- }
253
- };
254
-
255
- const data = {
256
- user: {
257
- name: 'John',
258
- email: 'john@example.com'
259
- }
260
- };
261
-
262
- const result = validator.validate(schema, data);
263
- console.log(result.valid); // true
264
- ```
265
-
266
- ### 示例 8: 验证数组
267
-
268
- ```javascript
269
- const schema = {
270
- type: 'array',
271
- items: { type: 'string' },
272
- minItems: 1,
273
- maxItems: 10
274
- };
275
-
276
- console.log(validator.validate(schema, ['a', 'b', 'c']).valid); // true
277
- console.log(validator.validate(schema, []).valid); // false (minItems)
278
- console.log(validator.validate(schema, [1, 2, 3]).valid); // false (type)
279
- ```
280
-
281
- ---
282
-
283
- ## 使用默认值
284
-
285
- 当 Validator 配置了 `useDefaults: true` 时,会自动应用 Schema 中的默认值。
286
-
287
- ```javascript
288
- const validator = new Validator({ useDefaults: true });
289
-
290
- const schema = {
291
- type: 'object',
292
- properties: {
293
- name: { type: 'string' },
294
- status: { type: 'string', default: 'active' }
295
- }
296
- };
297
-
298
- const result = validator.validate(schema, { name: 'John' });
299
-
300
- console.log(result.valid); // true
301
- console.log(result.data); // { name: 'John', status: 'active' }
302
- console.log(result.data.status); // 'active' (自动应用默认值)
303
- ```
304
-
305
- ---
306
-
307
- ## 使用已编译的验证函数
308
-
309
- 为了提高性能,可以先编译 Schema,然后重复使用编译后的验证函数。
310
-
311
- ```javascript
312
- // 编译 Schema
313
- const validateFn = validator.compile(schema);
314
-
315
- // 重复使用(性能更好)
316
- const result1 = validator.validate(validateFn, data1);
317
- const result2 = validator.validate(validateFn, data2);
318
- const result3 = validator.validate(validateFn, data3);
319
- ```
320
-
321
- ---
322
-
323
- ## 错误处理最佳实践
324
-
325
- ### 实践 1: 展示用户友好的错误信息
326
-
327
- ```javascript
328
- const result = validator.validate(schema, data);
329
-
330
- if (!result.valid) {
331
- // 格式化错误信息
332
- result.errors.forEach(err => {
333
- console.log(`字段 "${err.path}": ${err.message}`);
334
- });
335
-
336
- // 或者整体提示
337
- console.log(`验证失败,共 ${result.errors.length} 个错误`);
338
- }
339
- ```
340
-
341
- ### 实践 2: API 响应中返回错误
342
-
343
- ```javascript
344
- const result = validator.validate(schema, req.body);
345
-
346
- if (!result.valid) {
347
- return res.status(400).json({
348
- success: false,
349
- message: '数据验证失败',
350
- errors: result.errors.map(err => ({
351
- field: err.path,
352
- message: err.message
353
- }))
354
- });
355
- }
356
-
357
- // 验证通过,继续处理
358
- processData(result.data);
359
- ```
360
-
361
- ### 实践 3: 抛出异常
362
-
363
- ```javascript
364
- const result = validator.validate(schema, data);
365
-
366
- if (!result.valid) {
367
- const error = new ValidationError(result.errors, data);
368
- throw error;
369
- }
370
- ```
371
-
372
- ---
373
-
374
- ## 性能优化建议
375
-
376
- ### 建议 1: 复用 Validator 实例
377
-
378
- ```javascript
379
- // ✅ 好:复用实例
380
- const validator = new Validator();
381
-
382
- app.post('/api/users', (req, res) => {
383
- const result = validator.validate(userSchema, req.body);
384
- // ...
385
- });
386
-
387
- // ❌ 不好:每次创建新实例
388
- app.post('/api/users', (req, res) => {
389
- const validator = new Validator(); // 不推荐
390
- const result = validator.validate(userSchema, req.body);
391
- // ...
392
- });
393
- ```
394
-
395
- ### 建议 2: 预编译 Schema
396
-
397
- ```javascript
398
- // 应用启动时预编译
399
- const validateUser = validator.compile(userSchema);
400
- const validateProduct = validator.compile(productSchema);
401
-
402
- // 使用时直接验证(更快)
403
- app.post('/api/users', (req, res) => {
404
- const result = validator.validate(validateUser, req.body);
405
- // ...
406
- });
407
- ```
408
-
409
- ### 建议 3: 使用缓存
410
-
411
- ```javascript
412
- // 显式编译并复用缓存键
413
- const validateUser = validator.compile(schema, 'user-schema');
414
-
415
- console.log(validateUser(data));
416
- ```
417
-
418
- ---
419
-
420
- ## 常见问题
421
-
422
- ---
423
-
424
- ## 对应示例文件
425
-
426
- **示例入口**: [validate.ts](https://github.com/vextjs/schema-dsl/blob/main/examples/docs/validate.ts)
427
- **说明**: 覆盖顶层 `validate()` 的成功/失败路径、默认类型转换,以及关闭 `coerce` 后的行为差异。
428
-
429
- ### Q1: 如何验证可选字段?
430
-
431
- 不在 `required` 数组中的字段自动为可选:
432
-
433
- ```javascript
434
- const schema = {
435
- type: 'object',
436
- properties: {
437
- name: { type: 'string' },
438
- age: { type: 'number' } // age 是可选的
439
- },
440
- required: ['name'] // 只有 name 是必填的
441
- };
442
- ```
443
-
444
- ### Q2: 如何允许额外字段?
445
-
446
- JSON Schema 默认允许额外字段。如果要禁止额外字段:
447
-
448
- ```javascript
449
- const schema = {
450
- type: 'object',
451
- properties: {
452
- name: { type: 'string' }
453
- },
454
- additionalProperties: false // 禁止额外字段
455
- };
456
- ```
457
-
458
- ### Q3: 如何验证多种类型?
459
-
460
- 使用 `anyOf` 或 `oneOf`:
461
-
462
- ```javascript
463
- const schema = {
464
- type: 'object',
465
- properties: {
466
- value: {
467
- anyOf: [
468
- { type: 'string' },
469
- { type: 'number' }
470
- ]
471
- }
472
- }
473
- };
474
- ```
475
-
476
- ### Q4: 性能如何?
477
-
478
- 基于 ajv,业界最快的 JSON Schema 验证器:
479
- - 验证速度 >15,000 ops/s
480
- - 内置编译缓存
481
- - 支持批量验证优化
482
-
483
- ---
484
-
485
- ## 相关文档
486
-
487
- - [Validator 类概述](./validator.md)
488
- - [compile 方法](./compile.md) - 编译 Schema 提升性能
489
- - [validateBatch 方法](./validate-batch.md) - 批量验证
490
- - [addKeyword 方法](./add-keyword.md) - 添加自定义验证
491
- - [JSON Schema 基础](./json-schema-basics.md)
492
-
493
- ---
494
-
495
- ## 外部参考
496
-
497
- - [JSON Schema 官方文档](https://json-schema.org/)
498
- - [ajv 文档](https://ajv.js.org/)
499
- - [JSON Schema Validator](https://www.jsonschemavalidator.net/) - 在线测试工具
500
-
501
- ---
502
-
503
-
504
- **最后更新**: 2025-12-24
505
-
506
-
1
+ # validate 方法详细文档
2
+
3
+ ## 📑 目录
4
+
5
+ ### 基础概念
6
+ - [概述](#概述) - validate 方法介绍
7
+ - [方法签名](#方法签名) - API 定义
8
+
9
+ ### 参数详解
10
+ - [参数详解](#参数详解)
11
+ - [schema 参数](#schema-参数)
12
+ - [options 对象属性](#options-对象属性)
13
+ - [返回值详解](#返回值详解)
14
+ - [valid (Boolean)](#valid-boolean)
15
+ - [errors (Array)](#errors-array)
16
+ - [data (Any)](#data-any)
17
+
18
+ ### 使用示例
19
+ - [基础示例](#基础示例)
20
+ - [示例 1: 验证简单对象](#示例-1-验证简单对象)
21
+ - [示例 2: 验证复杂对象](#示例-2-验证复杂对象)
22
+ - [示例 3: 处理验证错误](#示例-3-处理验证错误)
23
+ - [示例 4: 使用默认值](#示例-4-使用默认值)
24
+
25
+ ### 高级功能
26
+ - [高级用法](#高级用法)
27
+ - [批量验证](#批量验证)
28
+ - [自定义错误格式](#自定义错误格式)
29
+ - [性能优化](#性能优化)
30
+
31
+ ### 参考资料
32
+ - [相关文档](#相关文档)
33
+ - [API 参考](#api-参考)
34
+
35
+ ---
36
+
37
+ ## 概述
38
+
39
+ `validate` 是 Validator 类的核心方法,用于验证数据是否符合 JSON Schema 定义。基于高性能的 ajv 验证器实现。
40
+
41
+ ---
42
+
43
+ ## 方法签名
44
+
45
+ ```javascript
46
+ validator.validate(schema, data, options = {})
47
+ ```
48
+
49
+ **参数说明**:
50
+ - `schema` (Object|Function): JSON Schema 对象或已编译的验证函数
51
+ - `data` (Any): 待验证的数据
52
+ - `options` (Object): 验证选项(可选)
53
+
54
+ **返回值**:
55
+ ```javascript
56
+ {
57
+ valid: Boolean, // 是否有效
58
+ errors: Array, // 成功时为空数组,失败时为错误列表
59
+ data: Any // 当前实现会返回本次验证数据(可能被 useDefaults 修改)
60
+ }
61
+ ```
62
+
63
+ 当前实现中,`data` 与 `errors` 都会随结果一并返回:成功时 `errors` 为空数组,验证失败时仍会保留 `data` 以便排查输入。
64
+
65
+ ---
66
+
67
+ ## 参数详解
68
+
69
+ ### schema 参数
70
+
71
+ JSON Schema 对象,支持 JSON Schema Draft 7 标准。
72
+
73
+ | 参数类型 | 说明 | 来源 |
74
+ |---------|------|------|
75
+ | Object | JSON Schema 对象 | JSON Schema 标准 ✅ |
76
+ | Function | 已编译的验证函数(通过 `compile()` 生成) | ajv ✅ |
77
+
78
+ ### options 对象属性
79
+
80
+ `validator.validate(schema, data, options)` 当前按本次调用实际读取以下参数:
81
+
82
+ | 参数 | 类型 | 必填 | 默认值 | 说明 |
83
+ |------|------|------|--------|------|
84
+ | `format` | Boolean | 否 | `true` | 是否格式化错误信息 |
85
+ | `locale` | String | 否 | — | 动态指定语言,如 `'zh-CN'`、`'en-US'`、`'ja-JP'` |
86
+ | `messages` | Object | 否 | — | 自定义错误消息覆盖 |
87
+
88
+ ### 相关配置入口
89
+
90
+ 以下能力**不属于** `validator.validate(schema, data, options)` 的逐次调用参数:
91
+
92
+ | 能力 | 正确入口 | 说明 |
93
+ |------|----------|------|
94
+ | `allErrors` / `useDefaults` / `coerceTypes` / `removeAdditional` / `cache` | `new Validator(options)` | 这些配置在创建 `Validator` 实例时注入到底层 AJV / 缓存层 |
95
+ | `strict` | Schema 本身 | 如果需要禁止额外字段,请在 schema 层使用 `DslBuilder.strict()` 或等价的 schema 级约束 |
96
+ | `coerce` | 顶层 `validate()` / `validateAsync()` 便捷函数 | 顶层 helper 默认会做字符串 → 数字 / 布尔值的便捷转换,传 `{ coerce: false }` 可关闭 |
97
+
98
+ 如果你需要在**单次调用**中覆盖错误输出,请使用上表中的 `format`、`locale`、`messages`;如果你需要调整验证器行为,请优先在 `Validator` 构造阶段配置。
99
+
100
+ ---
101
+
102
+ ## 返回值详解
103
+
104
+ ### valid (Boolean)
105
+
106
+ 表示数据是否通过验证。
107
+
108
+ ```javascript
109
+ result.valid === true // 验证通过
110
+ result.valid === false // 验证失败
111
+ ```
112
+
113
+ ### errors (Array)
114
+
115
+ 验证错误列表。当前实现成功时返回空数组,验证失败时包含详细错误信息。
116
+
117
+ **错误对象结构**:
118
+ ```javascript
119
+ {
120
+ path: String, // 错误字段路径,如 'user.email'
121
+ message: String, // 错误描述信息
122
+ keyword: String, // 触发的 Schema 关键字
123
+ params: Object // 错误相关参数
124
+ }
125
+ ```
126
+
127
+ ### data (Any)
128
+
129
+ 验证后的数据。当前实现即使在验证失败时也会保留本次验证数据,便于排查输入;如果 Validator 配置了 `useDefaults: true`,则也可能反映 Schema 中应用后的默认值。
130
+
131
+ ---
132
+
133
+ ## 基础示例
134
+
135
+ ### 示例 1: 验证简单对象
136
+
137
+ ```javascript
138
+ const { Validator } = require('schema-dsl');
139
+
140
+ const validator = new Validator();
141
+
142
+ const schema = {
143
+ type: 'object',
144
+ properties: {
145
+ name: { type: 'string' },
146
+ age: { type: 'number' }
147
+ },
148
+ required: ['name']
149
+ };
150
+
151
+ const result = validator.validate(schema, {
152
+ name: 'John',
153
+ age: 25
154
+ });
155
+
156
+ console.log(result.valid); // true
157
+ console.log(result.errors); // []
158
+ ```
159
+
160
+ ### 示例 2: 处理验证失败
161
+
162
+ ```javascript
163
+ const result = validator.validate(schema, {
164
+ age: 'invalid'
165
+ });
166
+
167
+ console.log(result.valid); // false
168
+ console.log(result.errors);
169
+ // 当前实现返回格式化后的错误列表:
170
+ // [
171
+ // { path: 'name', message: 'name不能为空' },
172
+ // { path: 'age', message: 'age应该是 number 类型' }
173
+ // ]
174
+ ```
175
+
176
+ ---
177
+
178
+ ## 高级示例
179
+
180
+ ### 示例 3: 验证字符串约束
181
+
182
+ ```javascript
183
+ const schema = {
184
+ type: 'string',
185
+ minLength: 3,
186
+ maxLength: 32,
187
+ pattern: '^[a-zA-Z0-9]+$'
188
+ };
189
+
190
+ // 有效数据
191
+ console.log(validator.validate(schema, 'john123').valid); // true
192
+
193
+ // 太短
194
+ console.log(validator.validate(schema, 'ab').valid); // false
195
+
196
+ // 包含非法字符
197
+ console.log(validator.validate(schema, 'john-123').valid); // false
198
+ ```
199
+
200
+ ### 示例 4: 验证数字范围
201
+
202
+ ```javascript
203
+ const schema = {
204
+ type: 'number',
205
+ minimum: 0,
206
+ maximum: 100
207
+ };
208
+
209
+ console.log(validator.validate(schema, 50).valid); // true
210
+ console.log(validator.validate(schema, -1).valid); // false
211
+ console.log(validator.validate(schema, 101).valid); // false
212
+ ```
213
+
214
+ ### 示例 5: 验证邮箱格式
215
+
216
+ ```javascript
217
+ const schema = {
218
+ type: 'string',
219
+ format: 'email'
220
+ };
221
+
222
+ console.log(validator.validate(schema, 'test@example.com').valid); // true
223
+ console.log(validator.validate(schema, 'invalid-email').valid); // false
224
+ ```
225
+
226
+ ### 示例 6: 验证枚举值
227
+
228
+ ```javascript
229
+ const schema = {
230
+ type: 'string',
231
+ enum: ['active', 'inactive', 'pending']
232
+ };
233
+
234
+ console.log(validator.validate(schema, 'active').valid); // true
235
+ console.log(validator.validate(schema, 'invalid').valid); // false
236
+ ```
237
+
238
+ ### 示例 7: 验证嵌套对象
239
+
240
+ ```javascript
241
+ const schema = {
242
+ type: 'object',
243
+ properties: {
244
+ user: {
245
+ type: 'object',
246
+ properties: {
247
+ name: { type: 'string' },
248
+ email: { type: 'string', format: 'email' }
249
+ },
250
+ required: ['name', 'email']
251
+ }
252
+ }
253
+ };
254
+
255
+ const data = {
256
+ user: {
257
+ name: 'John',
258
+ email: 'john@example.com'
259
+ }
260
+ };
261
+
262
+ const result = validator.validate(schema, data);
263
+ console.log(result.valid); // true
264
+ ```
265
+
266
+ ### 示例 8: 验证数组
267
+
268
+ ```javascript
269
+ const schema = {
270
+ type: 'array',
271
+ items: { type: 'string' },
272
+ minItems: 1,
273
+ maxItems: 10
274
+ };
275
+
276
+ console.log(validator.validate(schema, ['a', 'b', 'c']).valid); // true
277
+ console.log(validator.validate(schema, []).valid); // false (minItems)
278
+ console.log(validator.validate(schema, [1, 2, 3]).valid); // false (type)
279
+ ```
280
+
281
+ ---
282
+
283
+ ## 使用默认值
284
+
285
+ 当 Validator 配置了 `useDefaults: true` 时,会自动应用 Schema 中的默认值。
286
+
287
+ ```javascript
288
+ const validator = new Validator({ useDefaults: true });
289
+
290
+ const schema = {
291
+ type: 'object',
292
+ properties: {
293
+ name: { type: 'string' },
294
+ status: { type: 'string', default: 'active' }
295
+ }
296
+ };
297
+
298
+ const result = validator.validate(schema, { name: 'John' });
299
+
300
+ console.log(result.valid); // true
301
+ console.log(result.data); // { name: 'John', status: 'active' }
302
+ console.log(result.data.status); // 'active' (自动应用默认值)
303
+ ```
304
+
305
+ ---
306
+
307
+ ## 使用已编译的验证函数
308
+
309
+ 为了提高性能,可以先编译 Schema,然后重复使用编译后的验证函数。
310
+
311
+ ```javascript
312
+ // 编译 Schema
313
+ const validateFn = validator.compile(schema);
314
+
315
+ // 重复使用(性能更好)
316
+ const result1 = validator.validate(validateFn, data1);
317
+ const result2 = validator.validate(validateFn, data2);
318
+ const result3 = validator.validate(validateFn, data3);
319
+ ```
320
+
321
+ ---
322
+
323
+ ## 错误处理最佳实践
324
+
325
+ ### 实践 1: 展示用户友好的错误信息
326
+
327
+ ```javascript
328
+ const result = validator.validate(schema, data);
329
+
330
+ if (!result.valid) {
331
+ // 格式化错误信息
332
+ result.errors.forEach(err => {
333
+ console.log(`字段 "${err.path}": ${err.message}`);
334
+ });
335
+
336
+ // 或者整体提示
337
+ console.log(`验证失败,共 ${result.errors.length} 个错误`);
338
+ }
339
+ ```
340
+
341
+ ### 实践 2: API 响应中返回错误
342
+
343
+ ```javascript
344
+ const result = validator.validate(schema, req.body);
345
+
346
+ if (!result.valid) {
347
+ return res.status(400).json({
348
+ success: false,
349
+ message: '数据验证失败',
350
+ errors: result.errors.map(err => ({
351
+ field: err.path,
352
+ message: err.message
353
+ }))
354
+ });
355
+ }
356
+
357
+ // 验证通过,继续处理
358
+ processData(result.data);
359
+ ```
360
+
361
+ ### 实践 3: 抛出异常
362
+
363
+ ```javascript
364
+ const result = validator.validate(schema, data);
365
+
366
+ if (!result.valid) {
367
+ const error = new ValidationError(result.errors, data);
368
+ throw error;
369
+ }
370
+ ```
371
+
372
+ ---
373
+
374
+ ## 性能优化建议
375
+
376
+ ### 建议 1: 复用 Validator 实例
377
+
378
+ ```javascript
379
+ // ✅ 好:复用实例
380
+ const validator = new Validator();
381
+
382
+ app.post('/api/users', (req, res) => {
383
+ const result = validator.validate(userSchema, req.body);
384
+ // ...
385
+ });
386
+
387
+ // ❌ 不好:每次创建新实例
388
+ app.post('/api/users', (req, res) => {
389
+ const validator = new Validator(); // 不推荐
390
+ const result = validator.validate(userSchema, req.body);
391
+ // ...
392
+ });
393
+ ```
394
+
395
+ ### 建议 2: 预编译 Schema
396
+
397
+ ```javascript
398
+ // 应用启动时预编译
399
+ const validateUser = validator.compile(userSchema);
400
+ const validateProduct = validator.compile(productSchema);
401
+
402
+ // 使用时直接验证(更快)
403
+ app.post('/api/users', (req, res) => {
404
+ const result = validator.validate(validateUser, req.body);
405
+ // ...
406
+ });
407
+ ```
408
+
409
+ ### 建议 3: 使用缓存
410
+
411
+ ```javascript
412
+ // 显式编译并复用缓存键
413
+ const validateUser = validator.compile(schema, 'user-schema');
414
+
415
+ console.log(validateUser(data));
416
+ ```
417
+
418
+ ---
419
+
420
+ ## 常见问题
421
+
422
+ ---
423
+
424
+ ## 对应示例文件
425
+
426
+ **示例入口**: [validate.ts](https://github.com/vextjs/schema-dsl/blob/main/examples/docs/validate.ts)
427
+ **说明**: 覆盖顶层 `validate()` 的成功/失败路径、默认类型转换,以及关闭 `coerce` 后的行为差异。
428
+
429
+ ### Q1: 如何验证可选字段?
430
+
431
+ 不在 `required` 数组中的字段自动为可选:
432
+
433
+ ```javascript
434
+ const schema = {
435
+ type: 'object',
436
+ properties: {
437
+ name: { type: 'string' },
438
+ age: { type: 'number' } // age 是可选的
439
+ },
440
+ required: ['name'] // 只有 name 是必填的
441
+ };
442
+ ```
443
+
444
+ ### Q2: 如何允许额外字段?
445
+
446
+ JSON Schema 默认允许额外字段。如果要禁止额外字段:
447
+
448
+ ```javascript
449
+ const schema = {
450
+ type: 'object',
451
+ properties: {
452
+ name: { type: 'string' }
453
+ },
454
+ additionalProperties: false // 禁止额外字段
455
+ };
456
+ ```
457
+
458
+ ### Q3: 如何验证多种类型?
459
+
460
+ 使用 `anyOf` 或 `oneOf`:
461
+
462
+ ```javascript
463
+ const schema = {
464
+ type: 'object',
465
+ properties: {
466
+ value: {
467
+ anyOf: [
468
+ { type: 'string' },
469
+ { type: 'number' }
470
+ ]
471
+ }
472
+ }
473
+ };
474
+ ```
475
+
476
+ ### Q4: 性能如何?
477
+
478
+ 基于 ajv,业界最快的 JSON Schema 验证器:
479
+ - 验证速度 >15,000 ops/s
480
+ - 内置编译缓存
481
+ - 支持批量验证优化
482
+
483
+ ---
484
+
485
+ ## 相关文档
486
+
487
+ - [Validator 类概述](./validator.md)
488
+ - [compile 方法](./compile.md) - 编译 Schema 提升性能
489
+ - [validateBatch 方法](./validate-batch.md) - 批量验证
490
+ - [addKeyword 方法](./add-keyword.md) - 添加自定义验证
491
+ - [JSON Schema 基础](./json-schema-basics.md)
492
+
493
+ ---
494
+
495
+ ## 外部参考
496
+
497
+ - [JSON Schema 官方文档](https://json-schema.org/)
498
+ - [ajv 文档](https://ajv.js.org/)
499
+ - [JSON Schema Validator](https://www.jsonschemavalidator.net/) - 在线测试工具
500
+
501
+ ---
502
+
503
+
504
+ **最后更新**: 2025-12-24
505
+
506
+