JSON Schema与AJV+JsonForms如何实现校验警告而非阻断性错误
可行实现方案
核心思路
JSON Schema原生不支持校验分级能力,我们通过AJV自定义扩展字段+前后端统一处理逻辑实现「建议必填/警告级校验」能力,完全兼容现有通用架构,不会影响原有强制校验逻辑。
步骤1:AJV扩展自定义警告级校验关键词
给AJV注册x-recommended-required自定义关键词,用于标记建议必填的字段,校验时仅生成警告标记,不触发校验失败,该扩展代码前后端统一引用即可保证规则一致:
// 通用AJV初始化扩展代码 ajv = createAjv({ schemaId: 'auto', allErrors: true, jsonPointers: true, errorDataPath: 'property', }); // 注册建议必填自定义关键词 ajv.addKeyword({ keyword: 'x-recommended-required', type: 'object', schemaType: 'array', errors: true, compile: (schema) => { return (data) => { const missingFields = schema.filter(field => data?.[field] === undefined || data?.[field] === null); if (missingFields.length > 0) { const warnErrors = missingFields.map(field => ({ keyword: 'x-recommended-required', dataPath: `/${field}`, message: `字段${field}为建议必填项,建议填写后提交`, params: { missingProperty: field }, isWarning: true // 核心标记,用于区分警告和强制错误 })); // 挂载警告信息到AJV错误列表,不影响校验结果 ajv.errors = ajv.errors ? [...ajv.errors, ...warnErrors] : warnErrors; } // 始终返回true,不会触发校验失败 return true; }; } });
步骤2:修改数据Schema适配建议必填需求
在需要的对象节点添加x-recommended-required配置,填写建议必填的字段名即可,不需要修改其他原有配置,示例如下:
{ "type": "object", "properties": { "group1": { "type": "object", "properties": { "level1": { "type": "integer", "enum": [0, 1, 2, 3, 4, 5, 6] }, "level2": { "type": "integer", "enum": [0, 1, 2, 3, 4, 5, 6] }, "level3": { "type": "integer", "enum": [0, 1, 2, 3, 4, 5, 6] }, "level4": { "type": "integer", "enum": [0, 1, 2, 3, 4, 5, 6] } }, "additionalProperties": false, "required": [], // 新增配置:group1下level1、level2为建议必填项 "x-recommended-required": ["level1", "level2"] }, "group2": { "type": "object", "properties": { "level1": { "type": "integer", "enum": [0, 1, 2, 3, 4, 5, 6] }, "level2": { "type": "integer", "enum": [0, 1, 2, 3, 4, 5, 6] }, "level3": { "type": "integer", "enum": [0, 1, 2, 3, 4, 5, 6] }, "level4": { "type": "integer", "enum": [0, 1, 2, 3, 4, 5, 6] } }, "additionalProperties": false, "required": [] } } }
步骤3:JsonForms前端逻辑适配
- 自定义校验结果渲染:修改JsonForms的错误渲染逻辑,判断错误对象携带
isWarning: true标记时,用黄色警告样式展示,不要标记为字段错误 - 提交逻辑调整:用户点击提交时,先执行校验,拆分校验结果为「强制错误」和「警告错误」两类
- 存在强制错误:阻止提交,正常提示用户修正
- 无强制错误、仅存在警告错误:弹出确认模态框,告知用户有未填写的建议项,用户确认后即可正常提交
- 无任何错误:直接提交
步骤4:NestJS后端逻辑适配
后端二次校验时,同样拆分校验结果,只要不存在非警告类的强制错误,即可放行数据入库,警告信息可按需存入操作日志留痕,不影响主流程。
方案优势
- 完全兼容现有通用架构,不需要为每个表单写自定义代码,新增建议必填表单仅需修改Schema配置即可
- 前后端校验逻辑完全统一,不会出现前后端规则不一致的问题
- 不侵入原有强制校验逻辑,两类校验规则互不干扰
备选方案:双Schema校验
如果不想扩展AJV关键词,也可以为每个需要警告的表单维护两套Schema:
- 强制校验Schema:用于前后端提交放行判断,校验通过即可入库
- 警告校验Schema:仅用于生成警告提示,校验结果不影响提交流程
该方案好处是不需要修改AJV初始化逻辑,缺点是同一个表单需要维护两套Schema,维护成本略高。
内容的提问来源于stack exchange,提问作者Eds Keizer
相关产品推荐
相关产品推荐

