在OpenAPI响应Schema中使用oneOf的Fastify报错问题排查
问题原因分析
你遇到的500错误核心原因是JSON Schema Draft 07的unevaluatedProperties: false不支持识别allOf中引用的schema属性:
- 你的
callEvent和appEvent通过allOf: [{ $ref: 'event' }]继承了event的属性,但在Draft 07规范下,unevaluatedProperties: false只会检查当前schema定义的属性(如type、num),不会识别event中的event_id、address等继承属性。 - 当响应返回包含这些继承属性的对象时,会被判定为"未授权的额外属性",触发验证失败。
- Swagger文档生成正常是因为其未严格执行
unevaluatedProperties的验证逻辑。
解决方案
方案一:升级到JSON Schema 2019-09(推荐)
从Draft 2019-09开始,unevaluatedProperties会自动识别allOf/anyOf/oneOf中引用的schema属性,完全适配你的继承场景:
- 修改Fastify的AJV配置,指定使用Draft 2019-09:
import Fastify from 'fastify'; const fastify = Fastify({ ajv: { customOptions: { strictSchema: false, draft: '2019-09' } } });
- 可选:在所有schema中添加Draft 2019-09的schema声明(规范写法):
// 在event schema顶部添加 $schema: 'https://json-schema.org/draft/2019-09/schema#'
方案二:移除unevaluatedProperties: false
如果业务不需要严格禁止未定义属性,直接删除callEvent和appEvent中的unevaluatedProperties: false字段,Draft 07即可正常验证继承属性。
方案三:使用AJV插件实现Draft 07下的属性合并
若必须保留Draft 07和严格属性限制,可通过ajv-merge-patch插件实现属性继承:
- 安装插件:
npm install ajv-merge-patch
- 配置Fastify引入插件:
import Fastify from 'fastify'; import ajvMergePatch from 'ajv-merge-patch'; const fastify = Fastify({ ajv: { customOptions: { draft: '07' }, plugins: [ajvMergePatch] } });
- 修改
callEvent和appEvent的继承方式为$merge:
// callEvent示例 server.addSchema({ $id: 'callEvent', type: 'object', $merge: { source: { $ref: 'event' }, with: { properties: { type: { type: 'string', const: 'call' }, num: { type: 'integer' }, result: { type: 'integer', minimum: 0, maximum: 3 } }, required: ['type', 'num', 'result'], unevaluatedProperties: false } } }); // appEvent示例 server.addSchema({ $id: 'appEvent', type: 'object', $merge: { source: { $ref: 'event' }, with: { properties: { type: { type: 'string', const: 'app' } }, required: ['type'], unevaluatedProperties: false } } });
内容的提问来源于stack exchange,提问作者Dalvine
相关产品推荐
相关产品推荐

