0

0

如何复用 Joi Schema 的属性定义而不继承验证规则

霞舞

霞舞

发布时间:2026-01-05 19:28:02

|

420人浏览过

|

来源于php中文网

原创

如何复用 Joi Schema 的属性定义而不继承验证规则

本文介绍在 joi 中如何安全复用基础 schema 的字段定义,避免意外继承 `.xor()`、`.messages()` 等链式配置,通过 `object.keys()` 方法实现纯净的属性扩展。

Joi 的 Schema 实例是不可变(immutable)的,每次调用 .xor()、.messages()、.requiredKeys() 等方法都会返回一个全新 Schema 实例,而非修改原对象。这意味着:直接对已配置 .xor() 和 .messages() 的 Schema 调用 .keys() 或 .append(),不会污染原始定义,但若你从一个“已增强”的 Schema 出发(如 baseSchema.xor(...).messages(...)),再调用 .keys(),新 Schema 仍会携带之前所有规则 —— 这正是问题根源。

✅ 正确做法是:仅对“纯净”的基础 Schema(即仅含 .object({ ... }) 定义、未附加任何校验逻辑或消息)调用 .keys()

以下为推荐实践:

AI图像编辑器
AI图像编辑器

使用文本提示编辑、变换和增强照片

下载
const Joi = require('@hapi/joi'); // 或 @joi/browser(v17+)

// ✅ 第一步:定义纯净的基础字段结构(无 xor / messages)
const baseFields = Joi.object({
  a: Joi.string().trim().empty(null, ''),
  b: Joi.string().guid().empty(null),
});

// ✅ 第二步:基于 baseFields 构建不同用途的完整 Schema
const firstSchema = baseFields
  .xor('a', 'b')
  .messages({
    'object.missing': 'One of "a", "b" is required.',
    'object.xor': 'Only one of "a", "b" is allowed.',
  });

const extendedSchema = baseFields.keys({
  c: Joi.string().trim(),
});

const secondSchema = extendedSchema
  .xor('a', 'b', 'c')
  .messages({
    'object.missing': 'One of "a", "b", "c" is required.',
    'object.xor': 'Only one of "a", "b", "c" is allowed.',
  });

⚠️ 注意事项:

  • ❌ 避免 const baseSchema = Joi.object({...}).xor(...).messages(...); const reused = baseSchema.keys({...}); —— 此时 reused 仍含 xor 和 messages;
  • ✅ baseFields 必须是 纯 Joi.object() 实例,不带任何链式修饰;
  • .keys() 是浅合并:若传入同名键(如 a),会完全覆盖原定义;如需条件性扩展,可先用 .describe() 提取结构,或借助 Joi.compile() 动态构建;
  • Joi v17+ 中 .keys() 已取代旧版 .add(),语义更清晰,推荐统一使用。

总结:Joi 的复用核心在于分层设计——将字段声明(schema structure)与业务规则(validation logic + messages)解耦。baseFields 扮演「类型契约」角色,而各 .xor() + .messages() 组合则作为面向具体场景的「验证策略」。这种模式不仅提升可维护性,也天然支持单元测试中对字段定义的独立断言。

相关专题

更多
c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

520

2023.09.20

append用法
append用法

append是一个常用的命令行工具,用于将一个文件的内容追加到另一个文件的末尾。想了解更多append用法相关内容,可以阅读本专题下面的文章。

343

2023.10.25

python中append的用法
python中append的用法

在Python中,append()是列表对象的一个方法,用于向列表末尾添加一个元素。想了解更多append的更多内容,可以阅读本专题下面的文章。

1068

2023.11.14

python中append的含义
python中append的含义

本专题整合了python中append的相关内容,阅读专题下面的文章了解更多详细内容。

172

2025.09.12

c++主流开发框架汇总
c++主流开发框架汇总

本专题整合了c++开发框架推荐,阅读专题下面的文章了解更多详细内容。

3

2026.01.09

c++框架学习教程汇总
c++框架学习教程汇总

本专题整合了c++框架学习教程汇总,阅读专题下面的文章了解更多详细内容。

7

2026.01.09

学python好用的网站推荐
学python好用的网站推荐

本专题整合了python学习教程汇总,阅读专题下面的文章了解更多详细内容。

10

2026.01.09

学python网站汇总
学python网站汇总

本专题整合了学python网站汇总,阅读专题下面的文章了解更多详细内容。

1

2026.01.09

python学习网站
python学习网站

本专题整合了python学习相关推荐汇总,阅读专题下面的文章了解更多详细内容。

4

2026.01.09

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Java 教程
Java 教程

共578课时 | 43.9万人学习

国外Web开发全栈课程全集
国外Web开发全栈课程全集

共12课时 | 1.0万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号