为何OpenAPI 3的oneOf示例对象并非均能通过两个Schema校验?
关于JSON Schema中oneOf关键字的疑问解析
在Swagger的oneOf关键字规范示例中,定义了两个对象Schema,要求请求体必须符合Dog或Cat其中一个:
Dog: type: object properties: bark: type: boolean breed: type: string enum: [Dingo, Husky, Retriever, Shepherd] Cat: type: object properties: hunts: type: boolean age: type: integer
给出的三个测试JSON对象如下:
对象1
{ "bark": true, "breed": "Dingo" }
对象2
{ "bark": true, "hunts": true }
对象3
{ "bark": true, "hunts": true, "breed": "Husky", "age": 3 }
文档说明:对象1符合其中一个Schema(Dog),对象2不符合任一Schema,对象3同时符合两个Schema,因此对象2和3都不是合法请求体。
但这里存在疑问:为什么这三个对象不是都能通过两个Schema的校验?毕竟示例里没有使用任何对象校验关键字(比如additionalProperties: false、required),而且所有对象的属性类型都匹配,甚至用验证器测试时,空JSON都能通过这类简单对象Schema的校验。
问题解析
核心原因在于JSON Schema的默认开放特性:
- 未指定
required的Schema,对象不需要包含所有定义的属性,只要存在的属性符合类型要求就会通过校验; - 未指定
additionalProperties: false时,对象可以包含Schema中未定义的额外属性,不会导致校验失败。
文档的结论和实际校验结果矛盾,是因为示例的oneOf规则隐含了**“仅属于某一类”**的业务意图,但原始Schema没有通过关键字明确约束。
要实现文档描述的效果,需要给两个Schema补充约束:
- 添加
required关键字,明确必须包含的属性(比如Dog要求bark和breed,Cat要求hunts和age); - 添加
additionalProperties: false,禁止出现Schema外的额外属性。
修改后的Schema示例:
Dog: type: object required: [bark, breed] properties: bark: type: boolean breed: type: string enum: [Dingo, Husky, Retriever, Shepherd] additionalProperties: false Cat: type: object required: [hunts, age] properties: hunts: type: boolean age: type: integer additionalProperties: false
修改后:
- 对象1:包含Dog的必填属性,无额外属性,仅符合Dog Schema;
- 对象2:缺少Dog和Cat的必填属性,不符合任一Schema;
- 对象3:包含两个Schema的必填属性,同时符合两个Schema,触发oneOf的失败条件。
这就和文档的结论完全匹配了。
内容的提问来源于stack exchange,提问作者Semaphor
相关产品推荐
相关产品推荐

