0

0

如何复用 Joi Schema 的字段定义而不继承校验规则?

碧海醫心

碧海醫心

发布时间:2026-01-05 18:14:45

|

385人浏览过

|

来源于php中文网

原创

如何复用 Joi Schema 的字段定义而不继承校验规则?

本文介绍在 joi 中高效复用已有对象 schema 字段(如 `a`、`b`)的方法:通过 `schema.keys()` 动态扩展属性,避免误继承 `.xor()`、`.messages()` 等顶层配置,实现清晰、可维护的 schema 分层设计。

在使用 Joi 构建复杂数据校验逻辑时,常需复用基础字段定义(如公共字段 a、b),但又不希望连带继承其组合约束(如 .xor())或错误消息(.messages())。直接链式调用 .append() 或 .keys() 在已应用顶层规则的 schema 上会保留原有约束,导致行为不符合预期。

正确做法是:将基础字段定义封装为“纯净”的 Joi.object() 实例(不附加 .xor() 或 .messages()),再通过 .keys() 方法进行扩展。该方法仅合并键值定义,完全忽略原 schema 的校验元信息(如 xor、and、messages、label 等),确保干净复用。

以下是推荐实现:

CoCo
CoCo

智谱AI推出的首个有记忆的企业自主Agent智能体

下载
const Joi = require('@hapi/joi'); // Joi v17+(注意:v17.9.1+ 支持此用法)

// ✅ 纯净基础 Schema:仅定义字段结构,无组合规则与消息
const baseSchema = Joi.object({
  a: Joi.string().trim().empty(null, ''),
  b: Joi.string().guid().empty(null),
});

// ✅ 复用字段并新增 'c',生成新 object schema
const extendedSchema = baseSchema.keys({
  c: Joi.string().trim(),
});

// ✅ 分别添加各自所需的组合约束与消息
const firstSchema = baseSchema.xor('a', 'b')
  .messages({
    'object.missing': 'One of "a", "b" is required.',
    'object.xor': 'Only one of "a", "b" is allowed.',
  });

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.',
  });
⚠️ 注意事项:❌ 错误方式:baseSchema.append({ c: ... }) 或 baseSchema.keys({...}) 在已调用 .xor() 的 schema 上执行 —— 此时 baseSchema 已携带组合规则,.keys() 仍会保留它,导致 secondSchema 意外继承 xor('a','b');✅ 正确前提:baseSchema 必须是“未增强”的原始对象 schema(即仅 Joi.object({ ... }) 调用后立即保存,未链式添加 .xor()/.messages());? 进阶提示:可将 baseSchema 命名为 baseFields 以语义化其职责,提升代码可读性;? Joi v17+ 中 Joi.object().keys() 是标准且稳定 API;若使用旧版(v16 及以下),需改用 Joi.object().concat(Joi.object({...})),但语义稍弱且不推荐。

总结:Joi 的 Schema 设计应遵循「结构分离、约束后置」原则——字段定义(structure)与业务规则(validation logic)解耦。借助 .keys() 复用字段,再独立绑定 .xor()、.or()、.messages() 等,既能保障复用性,又能精准控制每层 Schema 的行为边界。

相关专题

更多
append用法
append用法

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

342

2023.10.25

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

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

1066

2023.11.14

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

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

170

2025.09.12

漫蛙2入口地址合集
漫蛙2入口地址合集

本专题整合了漫蛙2入口汇总,阅读专题下面的文章了解更多详细内容。

150

2026.01.06

AO3中文版地址汇总
AO3中文版地址汇总

本专题整合了AO3中文版地址合集,阅读专题下面的文章了解更多详细内容。

82

2026.01.06

python cv2模块教程大全
python cv2模块教程大全

本专题整合了python cv2模块相关教程,阅读专题下面的文章了解更多详细教程。

41

2026.01.06

python创建txt文件教程大全
python创建txt文件教程大全

本专题整合了python创建txt文件相关教程,阅读专题下面的文章了解更多详细内容。

21

2026.01.06

python去掉字符串空格教程大全
python去掉字符串空格教程大全

本专题整合了python去掉字符串空格教程大全,阅读专题下面的文章了解更多详细内容。

2

2026.01.06

Python /与// 教程大全
Python /与// 教程大全

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

23

2026.01.06

热门下载

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

精品课程

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

共578课时 | 42.9万人学习

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

共12课时 | 0.9万人学习

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

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