JSON 架构:条件依赖
JSON schema: conditional dependency
我似乎无法弄清楚如何在 JSON 模式中实现某些目标。假设我有两个字段:status
和 quote
.
条件依赖如下:
- 如果
status
是 ["Y", "N"]
,那么 quote
是 必需的
- 如果
status
是枚举中的任何其他内容,那么 quote
不需要
- 如果
status
不在 JSON 中,那么 quote
可以是任何东西
我正在尝试使用以下架构实现此行为:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"quote": {
"type": "string",
},
"status": {
"type": "string",
"enum": ["Y", "N", "M", "A", "S"]
}
},
"oneOf": [
{
"properties": {
"status": {"enum": ["Y", "N"]}
},
"required": [
"quote"
]
},
{
"properties": {
"status": {"enum": ["Y", "N", "M", "A", "S"]}
}
}
]
}
前两个条件按预期工作,但只要 status
字段从 JSON 中遗漏,验证就会失败。想要的行为是,只要 status
字段不存在,我就可以拥有一个字段 quote
。
我怎样才能做到这一点?
更新
所以我设法实现了我最初的要求,但是,我现在有额外的要求。也就是说,我有一个额外的字段 author
,只要 status
是 ["M", "A"]
就需要它,否则它只是可选的。如果 status
不存在,则 quote
和 author
都可以是任何值。我试过如下:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"quote": { "type": "string" },
"author": { "type": "string" },
"status": { "enum": ["Y", "N", "M", "A", "S"] }
},
"allOf": [
{ "$ref": "#/definitions/y-or-n-requires-quote" },
{ "$ref": "#/definitions/m-or-a-requires-author" }
],
"definitions": {
"y-or-n-requires-quote": {
"anyOf": [
{ "not": { "$ref": "#/definitions/status-is-y-or-n" } },
{ "required": ["quote"] }
]
},
"m-or-a-requires-author": {
"anyOf": [
{ "not": { "$ref": "#/definitions/status-is-m-or-a" } },
{ "required": ["author"] }
]
},
"status-is-y-or-n": {
"properties": {
"status": { "enum": ["Y", "N"] }
}
},
"status-is-m-or-a": {
"properties": {
"status": { "enum": ["M", "A"] }
}
}
}
}
但是,使用此架构不适用于 JSON,其中 status
不存在。
您需要使用称为蕴涵(!A 或 B)的布尔逻辑概念。这是表达 if-then 约束的一种方式。在这种情况下,我们想表达的是:要么status不是"Y"/"N"要么quote is required.
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"quote": { "type": "string" },
"status": { "enum": ["Y", "N", "M", "A", "S"] }
},
"allOf": [
{ "$ref": "#/definitions/y-or-n-requires-quote" }
],
"definitions": {
"y-or-n-requires-quote": {
"anyOf": [
{ "not": { "$ref": "#/definitions/status-is-y-or-n" } },
{ "required": ["quote"] }
]
},
"status-is-y-or-n": {
"properties": {
"status": { "enum": ["Y", "N"] }
},
"required": ["status"]
}
}
}
请注意,draft-07 添加了“if”/“then”/“else”关键字以简化条件判断:
https://datatracker.ietf.org/doc/html/draft-handrews-json-schema-validation-00#section-6.6
如果您的工具不支持 draft-07,请考虑提交功能请求以更新它们:-)
我似乎无法弄清楚如何在 JSON 模式中实现某些目标。假设我有两个字段:status
和 quote
.
条件依赖如下:
- 如果
status
是["Y", "N"]
,那么quote
是 必需的 - 如果
status
是枚举中的任何其他内容,那么quote
不需要 - 如果
status
不在 JSON 中,那么quote
可以是任何东西
我正在尝试使用以下架构实现此行为:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"quote": {
"type": "string",
},
"status": {
"type": "string",
"enum": ["Y", "N", "M", "A", "S"]
}
},
"oneOf": [
{
"properties": {
"status": {"enum": ["Y", "N"]}
},
"required": [
"quote"
]
},
{
"properties": {
"status": {"enum": ["Y", "N", "M", "A", "S"]}
}
}
]
}
前两个条件按预期工作,但只要 status
字段从 JSON 中遗漏,验证就会失败。想要的行为是,只要 status
字段不存在,我就可以拥有一个字段 quote
。
我怎样才能做到这一点?
更新
所以我设法实现了我最初的要求,但是,我现在有额外的要求。也就是说,我有一个额外的字段 author
,只要 status
是 ["M", "A"]
就需要它,否则它只是可选的。如果 status
不存在,则 quote
和 author
都可以是任何值。我试过如下:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"quote": { "type": "string" },
"author": { "type": "string" },
"status": { "enum": ["Y", "N", "M", "A", "S"] }
},
"allOf": [
{ "$ref": "#/definitions/y-or-n-requires-quote" },
{ "$ref": "#/definitions/m-or-a-requires-author" }
],
"definitions": {
"y-or-n-requires-quote": {
"anyOf": [
{ "not": { "$ref": "#/definitions/status-is-y-or-n" } },
{ "required": ["quote"] }
]
},
"m-or-a-requires-author": {
"anyOf": [
{ "not": { "$ref": "#/definitions/status-is-m-or-a" } },
{ "required": ["author"] }
]
},
"status-is-y-or-n": {
"properties": {
"status": { "enum": ["Y", "N"] }
}
},
"status-is-m-or-a": {
"properties": {
"status": { "enum": ["M", "A"] }
}
}
}
}
但是,使用此架构不适用于 JSON,其中 status
不存在。
您需要使用称为蕴涵(!A 或 B)的布尔逻辑概念。这是表达 if-then 约束的一种方式。在这种情况下,我们想表达的是:要么status不是"Y"/"N"要么quote is required.
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"quote": { "type": "string" },
"status": { "enum": ["Y", "N", "M", "A", "S"] }
},
"allOf": [
{ "$ref": "#/definitions/y-or-n-requires-quote" }
],
"definitions": {
"y-or-n-requires-quote": {
"anyOf": [
{ "not": { "$ref": "#/definitions/status-is-y-or-n" } },
{ "required": ["quote"] }
]
},
"status-is-y-or-n": {
"properties": {
"status": { "enum": ["Y", "N"] }
},
"required": ["status"]
}
}
}
请注意,draft-07 添加了“if”/“then”/“else”关键字以简化条件判断:
https://datatracker.ietf.org/doc/html/draft-handrews-json-schema-validation-00#section-6.6
如果您的工具不支持 draft-07,请考虑提交功能请求以更新它们:-)