ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Midway 参数校验(Validation)组件实战指南:DTO 校验、校验管道与多验证器扩展

Midway 参数校验(Validation)组件实战指南:DTO 校验、校验管道与多验证器扩展 后端微服务云原生【免费下载链接】midway A Node.js Serverless Framework for front-end/full-stack developers. Build the application for next decade. Works on AWS, Alibaba Cloud, Tencent Cloud and traditional VM/Container. Super easy integrate with React and Vue. 项目地址https://gitcode.com/gh_mirrors/mi/midway点击查看免费下载本文以 Midway 官方文档 参数校验指南 为主体结合midwayjs/validation组件在仓库中的源码实现系统讲解从安装配置、Rule/Validate/Valid装饰器使用、内置校验管道到 Zod / class-validator 多验证器接入、自定义验证器与多语言错误文本的完整方案。读完本文你将能在一个标准 Midway 项目中彻底告别手写if/throw参数检查用声明式 DTO 完成参数的类型校验与自动转换。背景为什么要用 Validation 组件参数校验最常用的场景是控制器Controller同时你可以在任意 Class 中使用这一能力。我们先以控制器为例看一个原始的写法普通情况下从body上拿到所有 POST 结果需要逐个字段手工校验➜ my_midway_app tree . ├── src │ ├── controller │ │ └── user.ts │ ├── interface.ts │ └── service │ └── user.ts ├── test ├── package.json └── tsconfig.json// src/interface.ts export interface User { id: number; firstName: string; lastName: string; age: number; } // src/controller/home.ts import { Controller, Get, Provide } from midwayjs/core; Controller(/api/user) export class HomeController { Post(/) async updateUser(Body() user: User) { if (!user.id || typeof user.id ! number) { throw new Error(id error); } if (user.age 30) { throw new Error(age not match); } // xxx } }如果每个方法都需要这样校验代码会非常繁琐。针对这种情况Midway 提供了 Validation 组件配合Validate和Rule装饰器用来快速定义校验的规则帮助用户减少这些重复的代码。需要注意版本差异从v4.0.0起midwayjs/validation作为midwayjs/validate的升级替代方案推出两者是不同的包。midwayjs/validation提供更上层的校验抽象支持 joi / zod / class-validator并预留自定义校验器扩展midwayjs/validate仅基于 joi仍可用但不再新增功能建议逐步迁移。组件能力矩阵描述可用于标准项目✅可用于 Serverless✅可用于一体化✅包含独立主框架❌包含独立日志❌下文通用示例均以 joi 验证器展开。安装依赖需要安装 validation 组件以及对应验证器。以 joi 为例## 安装 validation 组件 $ npm i midwayjs/validation4 --save ## 选择一个或多个验证器 $ npm i midwayjs/validation-joi4 --save ## 基础库 $ npm i joi --save或者在package.json中增加如下依赖后重新安装{ dependencies: { midwayjs/validation: ^4.0.0, midwayjs/validation-joi: ^4.0.0, joi: ^17.13.3, // ... }, devDependencies: { // ... } }开启组件在configuration.ts中增加组件import { Configuration, App } from midwayjs/core; import * as koa from midwayjs/koa; import * as validation from midwayjs/validation; import { join } from path; Configuration({ imports: [ koa, validation, // ... 其他组件 ], importConfigs: [join(__dirname, ./config)], }) export class MainConfiguration { App() app: koa.Application; async onReady() { // ... } }从源码看组件定义于 packages/validation/src/configuration.ts其namespace为validation并隐式依赖midwayjs/i18n组件imports: [i18n]这也是后面多语言错误文本能够自动工作的原因。组件还内置了默认配置errorStatus: 422、throwValidateError: true。接下来在配置文件中设置验证器// src/config/config.default.ts import joi from midwayjs/validation-joi; export default { // ... validation: { // 配置验证器 validators: { joi, }, // 设置默认验证器 defaultValidator: joi } }组件启动时configuration.ts的init()会读取validation.validators配置并逐一注册到内部单例 registry 中如果未显式设置defaultValidator则默认使用第一个注册的验证器见setFirstValidatorToDefault。若validators未配置ValidationService初始化会抛出config.validation.validators is not set错误见 packages/validation/src/service.ts。校验规则Rule 装饰器通过Rule装饰器可以为 DTOData Transfer Object类的属性传递校验规则import { Rule } from midwayjs/validation; import * as Joi from joi; export class UserDTO { Rule(Joi.number().required()) id: number; Rule(Joi.string().required()) firstName: string; Rule(Joi.string().max(10)) lastName: string; Rule(Joi.number().max(60)) age: number; }Rule的实现非常轻量仅将规则写入属性的元数据RULES_KEY中见 packages/validation/src/decorator/rule.tsexport function Rule(rule: any): PropertyDecorator { return function (target, propertyKey: string) { MetadataManager.defineMetadata(RULES_KEY, rule, target, propertyKey); }; }joi 验证器在getSchema时会把这些属性规则收集起来组装成一个 joi 的 object schemaJoi.object(getRuleMeta(ClzType))见 packages/validation-joi/src/index.ts 的schemaHelper.getSchema。校验参数自动校验与 Validate 装饰器定义完类型之后就可以直接在业务代码中使用了框架将自动帮你校验和转换 DTO// src/controller/home.ts import { Controller, Get, Provide, Body } from midwayjs/core; import { UserDTO } from ./dto/user; Controller(/api/user) export class HomeController { Post(/) async updateUser(Body() user: UserDTO) { // user.id } }所有的校验代码都消失了业务变得更纯粹。当然记得把原来的 user interface 换成 Class校验依赖 Class 的元数据。一旦校验失败浏览器或控制台就会报出类似错误ValidationError: id is required同时由于定义了id的类型在拿到字符串的情况下会自动将 id 转换为数字async updateUser(Body() user: UserDTO ) { // typeof user.id number }自动校验之所以生效是因为组件在onReady时通过registerParameterPipes(WEB_ROUTER_PARAM_KEY, [ValidationPipe])把所有 Web 参数装饰器都接入了ValidationPipe见 packages/validation/src/configuration.ts。ValidationPipe会忽略基础类型与文件流参数以控制性能开销只对带 schema 的 Class 类型参数执行校验见 packages/validation/src/pipe.ts 的validate()方法。方法级别配置Validate如果需要对方法级别单独配置信息可以使用Validate装饰器比如单独配置错误状态// src/controller/home.ts import { Controller, Get, Provide } from midwayjs/core; import { Validate } from midwayjs/validation; import { UserDTO } from ./dto/user; Controller(/api/user) export class HomeController { Post(/) Validate({ errorStatus: 422, }) async updateUser(Body() user: UserDTO) { // user.id } }Validate装饰器可传递多个配置项其元数据定义见 packages/validation/src/decorator/validate.ts校验时由 ValidationService 读取并生效。支持的配置项如下配置项类型描述errorStatusnumber当校验出错时返回的 Http 状态码在 http 场景生效默认 422localestring校验出错文本的默认语言默认为en_US会根据 i18n 组件的规则切换throwValidateErrorboolean是否抛出校验错误默认true如果设置为false则返回校验结果defaultValidatorstring设置默认使用的验证器这些配置项最终在ValidationService.validateWithSchema中与全局配置合并validationOptions?.throwValidateError ?? this.validateConfig.throwValidateError、validationOptions?.errorStatus ?? this.validateConfig.errorStatus校验失败且throwValidateError为真时抛出MidwayValidationError源码见 packages/validation/src/service.ts 第 107-119 行。校验结果统一的 ValidateResult 结构校验结果是一个对象包含校验的状态、错误、值等信息。Midway 对不同的验证器返回值做了封装统一了返回值的格式整体结构如下定义见 packages/validation/src/interface.tsinterface ValidateResult { /** * 校验是否成功 */ status: boolean; /** * 校验错误如果有多个错误会返回第一个错误 */ error?: any; /** * 校验的所有错误 */ errors?: any[]; /** * 校验错误信息如果有多个错误会返回第一个错误的信息 */ message?: string; /** * 校验的所有错误信息 */ messages?: string[]; /** * 校验额外信息 */ extra?: any; }不同验证器返回的数据都会被处理成相同的结构。以 joi 为例其validateWithSchema在result.error存在时统一输出status: false / error / errors / message / messages成功时输出status: true / value见 packages/validation-joi/src/index.ts。通用场景校验Valid 装饰器如果参数不是 DTO可以使用Valid装饰器进行校验它可以直接传递一个验证规则。使用 Joiimport { Controller, Get, Query } from midwayjs/core; import { Valid } from midwayjs/validation; import * as Joi from joi; Controller(/api/user) export class HomeController { Get(/) async getUser(Valid(Joi.number().required()) Query(id) id: number) { // ... } }使用 Zodimport { Controller, Get, Query } from midwayjs/core; import { Valid } from midwayjs/validation; import { z } from zod; Controller(/api/user) export class HomeController { Get(/) async getUser(Valid(z.number().min(1)) Query(id) id: number) { // ... } }在非 Web 场景下没有Body等 Web 类装饰器的情况下也可以使用Valid装饰器来进行校验import { Valid } from midwayjs/validation; import { Provide } from midwayjs/core; import { UserDTO } from ./dto/user; Provide() export class UserService { async updateUser(Valid() user: UserDTO) { // ... } }Valid的实现基于 Midway 自定义参数装饰器createCustomParamDecorator未显式传入 schema 时会在参数处理器中通过ValidationService.getSchema(originParamType)从 DTO 类推断 schema并挂载DecoratorValidPipe执行校验见 packages/validation/src/decorator/valid.ts 与 packages/validation/src/configuration.ts 的参数处理器注册。校验管道内置管道与基础类型校验如果你的参数是基础类型比如number、string、boolean可以使用组件提供的管道进行校验。默认的 Web 参数装饰器都可以在第二个参数传入管道例如import { ParseIntPipe } from midwayjs/validation; import { Controller, Post, Body } from midwayjs/core; Controller(/api/user) export class HomeController { Post(/update_age) async updateAge(Body(age, [ParseIntPipe]) age: number) { // ... } }ParseIntPipe管道可以将字符串、数字数据转换为数字这样从请求参数获取到的age字段则会通过管道的校验并转换为数字格式。组件提供的内置管道有ParseIntPipeParseFloatPipeParseBoolPipeDefaultValuePipeParseIntPipe转为整型数字import { ParseIntPipe } from midwayjs/validation; // ... async update(Body(age, [ParseIntPipe]) age: number) { return age; } update({ age: 12} ); 12 update({ age: 12.2} ); Error update({ age: abc} ); ErrorParseFloatPipe转为浮点数字import { ParseFloatPipe } from midwayjs/validation; // ... async update(Body(size, [ParseFloatPipe]) size: number) { return size; } update({ size: 12.2} ); 12.2 update({ size: 12} ); 12ParseBoolPipe转为布尔值import { ParseBoolPipe } from midwayjs/validation; // ... async update(Body(isMale, [ParseBoolPipe]) isMale: boolean) { return isMale; } update({ isMale: true} ); true update({ isMale: 0} ); ErrorDefaultValuePipe设定默认值import { DefaultValuePipe } from midwayjs/validation; // ... async update(Body(nickName, [new DefaultValuePipe(anonymous)]) nickName: string) { return nickName; } update({ nickName: undefined} ); anonymous从源码看packages/validation/src/pipe.tsParseIntPipe/ParseFloatPipe/ParseBoolPipe均继承自ParsePipe通过getSchema()从当前默认验证器的schemaHelper获取对应基础类型 schemajoi 下分别为Joi.number().integer().required()、Joi.number().required()、Joi.boolean().required()见 packages/validation-joi/src/index.ts校验成功后才返回转换后的值DefaultValuePipe则在值为undefined/null/NaN时返回构造时传入的默认值。自定义校验管道如果默认的管道不满足需求可以通过继承组件提供的ParsePipe类快速实现一个自定义校验管道import { Pipe } from midwayjs/core; import { ParsePipe, RuleType } from midwayjs/validation; Pipe() export class ParseCustomDataPipe extends ParsePipe { getSchema() { // ... } }getSchema方法用于返回一个校验规则。比如ParseIntPipe的代码如下管道执行时会自动获取这个 schema 进行校验并在校验成功后将值返回这里以 joi 为例import { Pipe } from midwayjs/core; import { ParsePipe, RuleType } from midwayjs/validation; import * as Joi from joi; Pipe() export class ParseIntPipe extends ParsePipe { getSchema() { return Joi.number().integer().required(); } }管道基类ParsePipe.transform的实现为以options.metadata[schema]即Valid(...)传入的 schema或this.getSchema()的结果为校验规则调用ValidationService.validateWithSchema成功后取value返回见 packages/validation/src/pipe.ts 第 95-103 行。校验规则进阶注意新版本中已经移除了RuleType的使用可以直接使用对应验证器的写法Rule装饰器可以传递不同类型的验证器的规则在Rule装饰器中使用getSchema方法时需要写成箭头函数。常见的 joi 校验写法import * as Joi from joi; Joi.number().required(); // 数字必填 Joi.string().empty(); // 字符串非必填 Joi.number().max(10).min(1); // 数字最大值和最小值 Joi.number().greater(10).less(50); // 数字大于 10小于 50 Joi.string().max(10).min(5); // 字符串长度最大 10最小 5 Joi.string().length(20); // 字符串长度 20 Joi.string().pattern(/^[abc]$/); // 字符串匹配正则格式 Joi.object().length(5); // 对象key 数量等于 5 Joi.array().items(Joi.string()); // 数组每个元素是字符串 Joi.array().max(10); // 数组最大长度为 10 Joi.array().min(10); // 数组最小长度为 10 Joi.array().length(10); // 数组长度为 10 Joi.string().allow(); // 非必填字段传入空字符串 export enum DeviceType { iOS ios, Android android, } Joi.string().valid(...Object.values(DeviceType)) // 根据枚举值校验级联校验Midway 支持每个校验的 Class 中的属性依旧是一个对象。给UserDTO增加一个属性school并赋予一个SchoolDTO类型import { Rule, getSchema } from midwayjs/validation; import * as Joi from joi; export class SchoolDTO { Rule(Joi.string().required()) name: string; Rule(Joi.string()) address: string; } export class UserDTO { Rule(Joi.number().required()) id: number; Rule(Joi.string().required()) firstName: string; Rule(Joi.string().max(10)) lastName: string; // 复杂对象 // 这里执行的时候 validator 还未注册所以需要使用箭头函数 Rule(() getSchema(SchoolDTO).required()) school: SchoolDTO; // 对象数组 Rule(() Joi.array().items(getSchema(SchoolDTO)).required()) schoolList: SchoolDTO[]; }此时Rule装饰器的参数可以为需要校验的这个类型本身。从源码看getRuleMeta会遍历类属性上的RULES_KEY元数据并对值为函数的规则先执行取结果见 packages/validation/src/service.ts 第 130-140 行这正是箭头函数延迟求值得以生效的原因——执行时验证器才完成注册。继承校验Midway 支持校验继承方式满足开发者抽离通用对象属性时做参数校验。例如下面CommonUserDTO抽离接口的通用属性然后UserDTO作为特殊接口需要的特定参数import { Rule } from midwayjs/validation; export class CommonUserDTO { Rule(Joi.string().required()) token: string; Rule(Joi.string()) workId: string; } export class UserDTO extends CommonUserDTO { Rule(Joi.string().required()) name: string; }老版本需要在子类上面加注解新版本不需要了。注意如果属性名相同则取当前属性的规则进行校验不会和父类合并。多类型校验从 v3.4.5 开始Midway 支持某个属性的不同类型校验。例如某个类型既可以是一个普通类型又可以是一个复杂类型import { Rule, getSchema } from midwayjs/validation; import * as Joi from joi; export class SchoolDTO { Rule(Joi.string().required()) name: string; Rule(Joi.string()) address: string; } export class UserDTO { Rule(Joi.string().required()) name: string; Rule(() Joi.alternatives([Joi.string(), getSchema(SchoolDTO)]).required()) school: string | SchoolDTO; }我们可以使用getSchema方法从某个 DTO 拿到当前的 schema从而进行复杂的逻辑处理。从原有 DTO 创建新 DTO有时候我们希望从某个 DTO 中获取一部分属性变成一个新的 DTO 类。Midway 提供了PickDto和OmitDto两个方法根据现有的 DTO 类型创建新的 DTO。PickDto用于从现有的 DTO 中获取一些属性变成新的 DTOOmitDto用于将其中某些属性剔除比如// src/dto/user.ts import { Rule, PickDto } from midwayjs/validation; export class UserDTO { Rule(Joi.number().required()) id: number; Rule(Joi.string().required()) firstName: string; Rule(Joi.string().max(10)) lastName: string; Rule(Joi.number().max(60)) age: number; } // 继承出一个新的 DTO export class SimpleUserDTO extends PickDto(UserDTO, [firstName, lastName]) {} // const simpleUser new SimpleUserDTO(); // 只包含了 firstName 和 lastName 属性 // simpleUser.firstName xxx export class NewUserDTO extends OmitDto(UserDTO, [age]) {} // const newUser new NewUserDTO(); // newUser.age 定义和属性都不存在 // 使用 async login(Body() user: NewUserDTO) { // ... }多语言错误文本默认情况下Midway 提供了en_US和zh_CN两种校验的翻译文本所以在请求失败时会返回当前浏览器访问所指定的语言。joi 验证器的翻译文本位于 packages/validation-joi/locales并会在初始化时自动注入 i18n 的localeTable见 packages/validation-joi/src/index.ts 第 88-99 行。通过装饰器指定语言默认情况下会跟随 i18n 组件的defaultLocale以及浏览器访问语言情况返回消息不过我们可以在装饰器中指定当前翻译的语言Controller(/user) export class UserController { Post(/) Validate({ locale: en_US, }) async getUser(Body() bodyData: UserDTO) { // ... } }通过参数指定语言除了装饰器指定也可以使用标准的 i18n 通过参数指定语言的方式比如 Query 参数Get /user/get_user?localezh_CN更多的参数用法请参考 i18n 组件。其他语言的翻译默认情况下Midway 提供了en_US和zh_CN两种校验的翻译文本如果还需要额外的翻译可以配置在 i18n 中// src/config/config.default.ts export default { // ... i18n: { // 增加翻译 zh_TW: { validate: require(../../locales/zh_TW.json), }, }, };自定义错误文本如果只想定义某个 DTO 中某个规则的错误消息可以简单指定export class UserDTO { Rule(RuleType.number().required().error(new Error(my custom message))) id: number; }默认配置在src/config/config.default.ts中可以对 validation 组件做整体配置配置项类型描述errorStatusnumber当校验出错时返回的 Http 状态码在 http 场景生效默认 422localestring校验出错文本的默认语言默认为en_US会根据 i18n 组件的规则切换validatorsRecordstring, Function配置要使用的验证器defaultValidatorstring设置默认使用的验证器如果未设置则使用用户require的第一个验证器其中errorStatus与throwValidateError的默认值由组件配置直接提供见 packages/validation/src/configuration.ts 第 27-36 行。高级用法独立的校验服务组件底层提供了单例的ValidationService校验服务类如有必要可以在中间件或者独立的服务中使用import { ValidationService } from midwayjs/validation; export class UserService { Inject() validateService: ValidationService; async invoke() { // ... const result this.validateService.validate(UserDTO, { name: harry, nickName: harry, }, { throwValidateError: false, }); if (result.status) { // 成功 } else { // 失败 } } }ValidationService定义为Singleton()注入validation与i18n配置核心方法为validate(ClzType, value, validationOptions?)与validateWithSchema(schema, value, ...)见 packages/validation/src/service.ts。需要留意当throwValidateError为true默认时校验失败会直接抛出MidwayValidationError因此想拿到ValidateResult结果对象需要显式传{ throwValidateError: false }。使用 zod 验证器Midway 同时支持 Zod v3 和 Zod v4 两个版本可根据项目需求选择midwayjs/validation-zod- 支持 Zod v3 (3.x)midwayjs/validation-zod4- 支持 Zod v4 (4.x)Zod v3安装相关依赖包$ npm i midwayjs/validation4 midwayjs/validation-zod4 zod3 --save在配置文件中设置验证器// src/config/config.default.ts import zod from midwayjs/validation-zod; export default { // ... validation: { // 配置验证器 validators: { zod: zod, }, // 设置默认验证器 defaultValidator: zod } }然后就可以使用 Zod 的验证规则import { Rule } from midwayjs/validation; import { z } from zod; export class UserDTO { Rule(z.number().min(1)) id: number; Rule(z.string().min(1)) firstName: string; Rule(z.string().max(10)) lastName: string; Rule(z.number().max(60)) age: number; }Zod v3 验证器使用了zod-i18n-map提供的翻译支持包括简体中文 (zh-CN)、繁体中文 (zh-TW)、英语 (en)、日语 (ja)、韩语 (ko)、俄语 (ru) 在内的多种语言。如需添加更多语言可在 i18n 配置中挂载翻译表// src/config/config.default.ts export default { // ... i18n: { localeTable: { zh_TW: { zod: require(zod-i18n-map/locales/zh-TW/zod.json), }, }, } }Zod v4安装相关依赖包$ npm i midwayjs/validation4 midwayjs/validation-zod44 zod4 --save在配置文件中设置验证器// src/config/config.default.ts import zod from midwayjs/validation-zod4; export default { // ... validation: { // 配置验证器 validators: { zod: zod, }, // 设置默认验证器 defaultValidator: zod } }使用方式与 v3 一致import { Rule } from midwayjs/validation; import { z } from zod; export class UserDTO { Rule(z.number().min(1)) id: number; Rule(z.string().min(1)) firstName: string; Rule(z.string().max(10)) lastName: string; Rule(z.number().max(60)) age: number; }Zod v4 验证器使用了semihbou/zod-i18n-map提供的翻译同样支持简体中文 (zh-CN)、繁体中文 (zh-TW)、英语 (en)、日语 (ja)、韩语 (ko)、俄语 (ru) 等多种语言语言扩展配置方式同理// src/config/config.default.ts export default { // ... i18n: { localeTable: { zh_TW: { zod: require(semihbou/zod-i18n-map/locales/zh-TW/zod.json), }, }, } }使用 class-validator 验证器先安装class-validator和相关依赖包$ npm i midwayjs/validation4 midwayjs/validation-class-validator4 class-validator class-transformer --save在配置文件中设置验证器// src/config/config.default.ts import classValidator from midwayjs/validation-class-validator; export default { // ... validation: { validators: { class-validator: classValidator, }, defaultValidator: class-validator } }然后就可以使用class-validator的验证规则import { Rule } from midwayjs/validation; import { IsString, IsNumber } from class-validator; export class UserDTO { Rule(IsString()) name: string; Rule(IsNumber()) age: number; }默认针对class-validator的验证规则Midway 提供了zh_CN和en_US两种翻译文本。如需更多语言支持可将翻译文件拷贝到本地/locales/ru.json后配置// src/config/config.default.ts export default { // ... i18n: { // 配置验证器 localeTable: { ru_RU: { classValidator: require(../../locales/ru.json), }, }, } }混用验证器可以在同一个项目中配置多个验证器// src/config/config.default.ts import joi from midwayjs/validation-joi; import zod from midwayjs/validation-zod; export default { // ... validation: { // 配置验证器 validators: { joi: joi, zod: zod, }, // 设置默认验证器 defaultValidator: joi } }Rule装饰器的参数可以使用不同的校验规则import { Rule } from midwayjs/validation; import * as Joi from joi; import { z } from zod; export class UserDTO { Rule(Joi.number().required()) id: number; Rule(Joi.string().required()) name: string; } export class AnotherUserDTO { Rule(z.number()) id: number; Rule(z.string().min(1)) name: string; }注意你不能在同一个类中使用不同的验证器。可以通过defaultValidator手动选择指定哪种验证器生效Controller(/user) export class UserController { Post(/) Validate({ defaultValidator: zod, }) async getUser(Body() bodyData: AnotherUserDTO) { // ... } }在ValidationService中也可以指定import { ValidationService } from midwayjs/validation; export class UserService { Inject() validateService: ValidationService; async invoke() { // ... const result this.validateService.validate(UserDTO, { name: harry, nickName: harry, }, { defaultValidator: zod }); } }自定义验证器除了使用内置的 Joi 和 Zod 验证器你还可以实现自己的验证器。验证器需要实现IValidationService接口import { IMidwayContainer } from midwayjs/core; import { IValidationService, ValidateResult, ValidationExtendOptions } from midwayjs/validation; class CustomValidator implements IValidationServiceany { // 初始化验证器 async init(container: IMidwayContainer): Promisevoid { // 在这里进行初始化操作 } // 使用 schema 进行验证 validateWithSchema( schema: any, value: any, options: ValidationExtendOptions, validatorOptions: any ): ValidateResult { const res {} as ValidateResult; try { // 实现你的验证逻辑 res.status true; res.value value; // 可以在这里对值进行转换 } catch (error) { res.status false; res.error error; res.message error.message; } return res; } // 获取 schema getSchema(ClzType: any): any { // 实现获取 schema 的逻辑 } // 获取基础类型的 schema getIntSchema(): any { // 返回整数类型的 schema } getBoolSchema(): any { // 返回布尔类型的 schema } getFloatSchema(): any { // 返回浮点数类型的 schema } getStringSchema(): any { // 返回字符串类型的 schema } } // 导出验证器工厂函数 export default async (container: IMidwayContainer) { return new CustomValidator(); };然后在配置中使用自定义验证器// src/config/config.default.ts import customValidator from ./custom.validator; export default { validation: { validators: { custom: customValidator, // 注册自定义验证器 }, defaultValidator: custom // 设置为默认验证器 } };从接口定义看packages/validation/src/interface.ts一个完整的验证器模块包含validateServiceHandler异步工厂返回IValidationService实例与schemaHelper负责getSchema、基础类型 schema、OpenAPI 属性推断等。组件初始化时由registry.initValidators统一await实例化并调用init见 packages/validation/src/registry.ts所以同步与异步构造两种形式都会被正常兼容。常见问题1. Joi 中允许未定义的字段对于 Joi 验证器可以通过joi顶层配置允许未定义的字段// src/config/config.default.ts export default { // ... joi: { allowUnknown: true, } };该配置由 joi 验证器的validateServiceHandler读取初始化时通过configService.getConfiguration(joi)获取并在执行schema.validate(value, newValidatorOptions)时与默认选项、语言配置合并见 packages/validation-joi/src/index.ts 第 116、132-139 行。2. 处理校验错误上面提到Midway 会在校验失败时抛出MidwayValidationError错误可以在异常处理器中处理// src/filter/validate.filter import { Catch } from midwayjs/core; import { MidwayValidationError } from midwayjs/validation; import { Context } from midwayjs/koa; Catch(MidwayValidationError) export class ValidateErrorFilter { async catch(err: MidwayValidationError, ctx: Context) { return { status: 422, message: 校验参数错误, err.message, }; } }MidwayValidationError定义于 packages/validation/src/error.ts携带校验失败的错误消息、HTTP 状态码默认 422以及原始错误对象。3. 多语言未生效请使用浏览器不要直接使用 Postman 来测试——多语言切换依赖浏览器请求头携带的语言环境信息。赞分享后端微服务云原生【免费下载链接】midway A Node.js Serverless Framework for front-end/full-stack developers. Build the application for next decade. Works on AWS, Alibaba Cloud, Tencent Cloud and traditional VM/Container. Super easy integrate with React and Vue. 项目地址https://gitcode.com/gh_mirrors/mi/midway点击查看免费下载相关推荐Mac Mouse Fix 快速上手指南把普通鼠标调出触控板手感Mac Mouse Fix 快速上手指南把普通鼠标调出触控板手感 侧键按下去没反应滚轮一格一格地跳指针快慢全凭系统定——这是多数人在 Mac 上接一只外接后端微服务云原生beego core/validation 数据校验实战指南从字段校验到自定义验证器beego core/validation 数据校验实战指南从字段校验到自定义验证器 本文围绕 beego github.com/beego/beego/v后端Web框架Mongoose 数据校验Validation完全指南内置校验器、自定义校验与更新校验器Mongoose 数据校验Validation完全指南内置校验器、自定义校验与更新校验器 Mongoose 作为 MongoDB 的异步对象建模库其数据数据库后端上一篇3分钟掌握Windows窗口强制调整WindowResizer终极使用指南下一篇PvZ Tools 植物大战僵尸修改器从入门到精通完整指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表