AJV验证嵌套引用对象时忽略required规则问题求助
问题:AJV验证未检测到对象类型属性的必填字段缺失
我实现了一个使用AJV验证API响应与Schema匹配的类,通过_definitionsHelper存储可复用的Schema块。在BAR的Schema定义中,我将FOO字段的类型设置为['object', 'null'],但当模拟JSON响应中的FOO缺失必填属性'url'时,AJV验证却意外通过,未抛出预期的错误。
已排查的情况:
- 移除根级别属性时,AJV能正确抛出缺失字段的错误
- 将FOO的类型改为数组时,AJV可以正常检测到必填字段缺失,但实际API返回的FOO是对象而非数组
相关代码
SchemaUtilities类代码
import Ajv from 'ajv'; export default class SchemaUtilities { validateSchema = (schema, response) => { const ajv = new Ajv(); const validate = ajv.addSchema(this._definitionsHelper).compile(schema); const valid = validate(response); if (!valid) { this._getSchemaError(validate.errors).then((schemaError) => { throw new Error(`Schema validation failed. ${schemaError}`); }); } else { cy.log('Schema validated.'); } }; private _definitionsHelper = { $id: 'customDefinitions', definitions: { baseResponseProperties: { type: 'object', properties: { errorCode: { type: 'number' }, responseCode: { type: 'number' }, }, required: ['errorCode', 'responseCode'] }, FOO: { type: 'object', properties: { id: { type: 'number' }, definition: { type: 'number' }, url: { type: 'string' } }, required: ['id', 'definition', 'url'] }, BAR: { type: 'object', properties: { featureId: { type: 'number' }, order: { type: 'number' }, featureImageUrl: { type: 'string' }, navigationLinkType: { type: 'string' }, navigationLink: { type: ['string', 'null'] }, FOO: { type: ['object', 'null'], items: { $ref: 'customDefinitions#/definitions/FOO' } }, sku: { type: ['string', 'null'] }, yyyUrl: { type: ['string', 'null'] }, featureYYYAlignment: { type: ['string', 'null'] } }, required: ['featureId', 'order', 'featureImageUrl', 'navigationLinkType', 'navigationLink', 'FOO', 'sku', 'yyyUrl', 'featureYYYAlignment'] } }, }; private _getSchemaError = (getAjvError) => { return cy.wrap(`Field: ${getAjvError[0]['instancePath']} is invalid. Cause: ${getAjvError[0]['message'].replace(',', ', found ')}`); }; }
模拟JSON响应
{ "errorCode": 0, "responseCode": 0, "BAR": [{ "featureId": 2, "order": 2, "featureImageUrl": "x", "navigationLinkType": "x", "navigationLink": null, "FOO": { "id": 2, "definition": 2 }, "sku": "x", "yyyUrl": null, "featureYYYAlignment": "x" }] }
验证用Schema
export const featuresSchema = { type: 'object', $ref: 'customDefinitions#/definitions/baseResponseProperties', properties: { BAR: { type: 'array', items: { $ref: 'customDefinitions#/definitions/BAR' } } }, required: ['BAR'] };
解决方案
问题出在BAR定义中FOO字段的Schema写法错误:items关键字仅适用于数组类型,你用它来描述对象类型的FOO,AJV会忽略这个无效配置,只校验FOO是对象或null,不会去校验对象内部的结构和必填字段。
修正BAR定义中的FOO字段,直接用$ref引用FOO的Schema定义即可:
FOO: { type: ['object', 'null'], $ref: 'customDefinitions#/definitions/FOO' },
修改后,AJV会同时校验FOO的类型(对象或null),以及对象内部的必填属性是否存在,当FOO缺失'url'时就会抛出预期的验证错误。
内容的提问来源于stack exchange,提问作者Zuno
相关产品推荐
相关产品推荐

