我正在扩展现有功能,因此 API 负载需要更新。由于我无法控制的限制,我需要同时支持旧有效负载和新有效负载。此验证还需要根据新策略重新实现为 JsonSchema。
旧的有效负载是一成不变的,新的有效负载可能会进行一些调整,但我更愿意保持原样。
旧有效负载是:
{
"OPTION": {
"property1": "someString",
"property2": <integer>
}
}
新的有效负载将添加额外的属性以及创建多个对象的能力,例如:
{
"OPTION": {
"object1": {
"property1": "someString",
"property2": <integer>,
"property3": <boolean>
},
...
"objectN": {
"property1": "someString",
"property2": <integer>,
"property3": <boolean>
}
}
}
我最初的尝试没有成功。这是一个对我来说直觉上似乎正确的尝试。错误:[“属性‘property1’尚未定义,架构不允许附加属性。”、“属性‘property2’尚未定义,架构不允许附加属性。”
{
"$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
}
}
}
编辑:修复了错误的复制/粘贴
这是您想要使用
unevaluatedProperties
而不是 additionalProperties
的时候。
additionalProperties
只能看到直接模式对象中定义的属性。 它无法看到由直接模式对象的子模式定义的属性。
{
"properties": {
"foo": true // seen
},
"patternProperties": {
"^[a-z]+[0-9]+$": true // seen (property requires letters AND numbers)
},
"allOf": [
{
"properties": {
"bar": false // not seen
}
}
],
"additionalProperties": false
}
但是,
unevaluatedProperties
可以看到这些子模式的内部,因此对于上面的内容,如果您使用bar
代替,则可以看到unevaluatedProperties
。
您可能还想检查新设计的子模式。 子模式当前描述了
OPTIONS
值的数组,但新数据的示例是具有“optionN”属性的对象。
最后,一点重构可以通过隔离每种可能的形式来帮助提高可读性。 通过使用
$ref
和 $defs
,您可以创建支持每种表单的标记子模式。
{
"$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": [
{ "$ref": "#/$defs/legacy" },
{ "$ref": "#/$defs/theNewWay" }
],
"unevaluatedProperties": false
}
},
"$defs": {
"legacy": {
"type": "object",
"properties": {
"property1": {
"type": "string"
},
"property2": {
"type": "integer"
}
}
},
"theNewWay": { // obviously rename this :)
"type": "array", // (and review this schema, maybe)
"items": {
"type": "object",
"properties": {
"property1": {
"type": "string"
},
"property2": {
"type": "integer"
},
"property3": {
"type": "boolean"
},
"additionalProperties": false
}
}
}
}
}