如何编写兼容旧版与新版API Payload的JSON Schema?
解决API Payload多版本兼容的JSON Schema校验问题
需求背景
- 扩展现有API功能,需同时兼容旧版(legacy)Payload与新版Payload
- 必须通过JSON Schema实现格式校验,旧版结构固定,新版需保留原有多对象格式
旧版Payload结构
{ "OPTION": { "property1": "someString", "property2": 123 } }
新版Payload结构(支持多对象创建,新增property3)
{ "OPTION": { "object1": { "property1": "someString", "property2": 123, "property3": true }, "objectN": { "property1": "anotherString", "property2": 456, "property3": false } } }
原Schema问题
编写的Schema触发以下报错:
["Property 'property1' has not been defined and the schema does not allow additional properties.", "Property 'property2' has not been defined and the schema does not allow additional properties."]
原Schema代码:
{ "$schema": "http://json-schema.org/draft/2020-12/schema", "title": "Title", "description": "Version...", "type": "object", "patternProperties": { "^[A-Z0-9]*$": { "type": "object", "title": "sub-title", "description": "...", "examples": [ "OPTION" ], "oneOf": [ { "type": "object", "properties": { "property1": { "type": "string" }, "property2": { "type": "integer" } } }, { "type": "array", "items": { "type": "object", "properties": { "property1": { "type": "string" }, "property2": { "type": "integer" }, "property3": { "type": "boolean" }, "additionalProperties": false } } } ], "additionalProperties": false } } }
问题分析
- 新版分支错误使用
array类型,但实际新版OPTION的值是包含多个子对象的对象,而非数组 - 旧版分支未指定必填字段,也未明确禁止额外属性,导致校验逻辑模糊
additionalProperties被错误嵌套在properties中,未放在对象顶层关键字位置
修正后的Schema
{ "$schema": "http://json-schema.org/draft/2020-12/schema", "title": "API Payload Schema", "description": "兼容旧版与新版Payload格式", "type": "object", "patternProperties": { "^[A-Z0-9]*$": { "type": "object", "title": "OPTION 对象", "description": "支持旧版单对象或新版多对象结构", "oneOf": [ // 旧版格式:直接包含property1和property2 { "type": "object", "properties": { "property1": { "type": "string" }, "property2": { "type": "integer" } }, "required": ["property1", "property2"], "additionalProperties": false }, // 新版格式:任意键名对应包含property1/2/3的子对象 { "type": "object", "patternProperties": { "^.*$": { "type": "object", "properties": { "property1": { "type": "string" }, "property2": { "type": "integer" }, "property3": { "type": "boolean" } }, "required": ["property1", "property2"], "additionalProperties": false } }, "minProperties": 1, "additionalProperties": false } ] } }, "required": ["OPTION"], "additionalProperties": false }
关键修正说明
- 新版分支改为
object类型,通过patternProperties匹配任意子对象键名(如object1、objectN) - 旧版分支添加
required关键字确保必填字段存在,同时明确additionalProperties: false禁止冗余字段 - 调整
additionalProperties到正确层级,避免校验逻辑混乱 - 顶层添加
required: ["OPTION"]确保根节点必须包含OPTION字段 - 新版分支添加
minProperties: 1确保至少包含一个子对象
内容的提问来源于stack exchange,提问作者Matt
相关产品推荐
相关产品推荐

