#3108·joi

标准 JSON 架构: 错误和缺失的转换

作者: AbdelrahmanHafez创建于 2026年4月8日更新于 2026年4月11日
标签bug

问题:其他目标…

什么问题你在试图解决呢?

~standard.jsonSchema 输出中的两个错误和几个缺失的转换:

错误:

1. alternatives.match('all') 生成 anyOf 而不是 allOf

javascript
const schema = Joi.alternatives().try(Joi.string(), Joi.number()).match('all');
const json = schema['~standard'].jsonSchema.input();
// 实际: { anyOf: [...] }
// 预期: { allOf: [...] }

alternatives.js 中的代码只检查 match('one') -> oneOf,然后对其他所有内容使用 anyOf

javascript
const matchMode = schema._flags.match ?? 'any';
if (matchMode === 'one') {
    res.oneOf = matches;
}
else {
    res.anyOf = matches;  // 'all' 也会在这里出现
}

2. 使用 Joi.ref() 而不是字面值的规则生成无效的 JSON Schema

当一个规则接收 Joi.ref() 而不是一个字面值时,Ref 对象会直接被赋值为 JSON Schema 关键字值:

javascript
const schema = Joi.number().min(Joi.ref('other'));
const json = schema['~standard'].jsonSchema.input();
// 生成: { type: 'number', minimum: { ref: ... } }
// 这不是有效的 JSON Schema

数字、字符串和数组规则不检查 arg 是否为 Ref 之前就将其赋值。日期规则部分地处理了这个问题,通过检查 date instanceof Date,但其他类型则完全不进行保护。

由于 refs 根据运行时值(而不是 schema 定义)进行解析,因此没有标准的 JSON Schema 等效值。2020-12 版草案中没有 $data 关键字或跨字段引用机制。修复方法是,如果 arg 是一个 Ref,则跳过发布约束,类似于日期规则已经跳过 arg 不是 Date 实例的情况。