如何用AJV JSON Schema校验器校验嵌套对象中prop1的唯一性
使用AJV校验嵌套对象中所有子对象的prop1值唯一性
首先要纠正你给出的JSON示例的语法错误——JSON对象必须是键值对结构,不能直接在父对象中放置无键的子对象,正确的结构应该类似这样:
{ "obj2": { "item1": { "prop1": "baz", "prop2": 999 }, "item2": { "prop1": "qux", "prop2": 555 } } }
标准JSON Schema的关键字(比如针对数组的uniqueItems)确实不支持直接校验对象值的唯一性,但AJV允许通过自定义关键字实现这个需求,具体步骤如下:
1. 注册自定义校验关键字
初始化AJV实例后,注册一个自定义关键字(比如uniquePropValues),编写逻辑遍历父对象的所有子值,提取指定字段并检查唯一性:
const Ajv = require('ajv'); const ajv = new Ajv(); // 注册自定义关键字 ajv.addKeyword({ keyword: 'uniquePropValues', type: 'object', validate: function(schema, parentObj) { // schema参数是关键字的配置值,这里指定要检查的字段名,比如"prop1" const propName = schema; const propValues = []; // 遍历父对象的所有子值 for (const key in parentObj) { const childObj = parentObj[key]; // 跳过非对象类型的子值(根据需求调整) if (typeof childObj !== 'object' || childObj === null) continue; // 如果子对象没有目标字段,可选择抛出错误或忽略,这里选择忽略 if (!(propName in childObj)) continue; const value = childObj[propName]; // 检查值是否重复 if (propValues.includes(value)) { // 校验失败,返回false,可添加错误信息 this.errors = [{ keyword: 'uniquePropValues', message: `Duplicate value "${value}" for property "${propName}"`, params: { propName, duplicateValue: value } }]; return false; } propValues.push(value); } return true; }, errors: true // 允许自定义错误信息 });
2. 编写JSON Schema并使用自定义关键字
在Schema中,针对obj2字段使用自定义的uniquePropValues关键字,指定要检查的字段为prop1:
const schema = { type: 'object', properties: { obj2: { type: 'object', // 自定义关键字,指定要检查唯一的字段名 uniquePropValues: 'prop1', // 可选:先校验子对象的结构 additionalProperties: { type: 'object', properties: { prop1: { type: 'string' }, prop2: { type: 'integer' } }, required: ['prop1', 'prop2'] } } }, required: ['obj2'] };
3. 校验数据
使用AJV实例编译Schema并校验数据:
const validate = ajv.compile(schema); // 校验通过的示例数据 const validData = { "obj2": { "item1": { "prop1": "baz", "prop2": 999 }, "item2": { "prop1": "qux", "prop2": 555 } } }; console.log(validate(validData)); // 输出true // 校验失败的示例数据(prop1重复) const invalidData = { "obj2": { "item1": { "prop1": "baz", "prop2": 999 }, "item2": { "prop1": "baz", "prop2": 555 } } }; console.log(validate(invalidData)); // 输出false console.log(validate.errors); // 打印错误信息
注意事项
- 自定义关键字的逻辑可以根据需求调整:比如如果子对象必须包含
prop1字段,可以在遍历的时候添加校验,没有该字段直接返回失败。 - 如果需要支持更复杂的场景(比如嵌套多层对象、不同类型的
prop1值),可以扩展自定义关键字的逻辑。
内容的提问来源于stack exchange,提问作者N0514
相关产品推荐
相关产品推荐

