You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 14:38:16