在 JSON 架构中,我想添加一个验证,判断负载是否与下面匹配
{
"key1": "value1",
"key1": "value2"
}
然后期望第三个键“key3”具有任意值。
但如果 key1 和 key2 的值分别与 value1、value2 不匹配,则 key3 不应出现。
JSON 架构如下所示
{
"$async": true,
"additionalProperties": false,
"properties": {
"key1": {
"type": "string"
},
"key2": {
"type": "string"
}
},
"required": ["key1"],
"allOf": [
{
"if": {
"properties": {
"key1": {
"const": "value1"
},
"key2": {
"const": "value2"
}
}
},
"then": {
"properties": {
"key3": {
"type": "string"
}
},
"required": ["key3"]
},
"else": {
}
}
]
}
有效输入是
{
"key1": "value1",
"key2": "value2",
"key3": "some-value"
}
--------
{
"key1": "value1",
"key2": "other-value"
}
---------
{
"key1": "value1"
}
---------
{
"key1": "other-value",
"key2": "value2"
}
---------
{
"key1": "other-value1",
"key2": "other-value2"
}
无效输入
{
"key1": "value1",
"key2": "value2". // key3 should be present
}
--------
{
"key1": "hello",
"key2": "world",
"unexpected-key": "value" // Any other key should not be allowed
}
--------
{
"key1": "value1",
"key2": "other-value",
"key3": "abc" // should not be present
}
---------
{
"key1": "other-value",
"key2": "value2",
"key3": "abc" // should not be present
}
---------
{
"key1": "other-value1",
"key2": "other-value2",
"key3": "abc" // should not be present
}
对于以下有效负载,JSON schema validator
{
"key1": "value1",
"key2": "value2",
"key3": "abc"
}
抛出以下错误
Property 'key3' has not been defined and the schema does not allow additional properties.
如何实现此条件属性?
最佳答案
解决方案取决于您能够使用 JSON 架构的版本(或“草案”)。 2019-09 草案或更高版本提供了更清晰的解决方案,但在 07 草案中仍然有可能。
(在使用 implication method 引入 if/then/else
之前也是可能的,但今天我不会讨论这个。
使用 2019-09 或 2020-12 的最佳解决方案。
unevaluatedProperties
关键字可以“透视”应用程序关键字,例如 allOf
、if
和 else
。
与 Draft-07 的 additionalProperties
不同,unevaluatedProperties
在架构架构对象中的所有其他应用程序之后运行,并且可以了解在更深层次的嵌套应用程序中定义的已成功验证的属性值。
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"unevaluatedProperties": false,
"properties": {
"key1": {
"type": "string"
},
"key2": {
"type": "string"
}
},
"required": [
"key1"
],
"allOf": [
{
"if": {
"required": ["key2"],
"properties": {
"key1": {
"const": "value1"
},
"key2": {
"const": "value2"
}
}
},
"then": {
"required": ["key3"],
"properties": {
"key3": {
"type": "string"
}
}
}
}
]
}
对于测试 2019-09 及更高版本的草案,我建议使用 https://json-schema.hyperjump.io Playground
( https://jsonschema.dev 尚不支持 2019-09 及更高版本的草案)。
使用 Draft-07 的解决方案。
要使 additionalProperties: false
正常工作,需要在 properties
中的同一架构对象中定义属性(或匹配 patternProperties
) .
在第一个实例中,您不关心具体值,properties
对象中的值只是true
。值验证稍后处理。如果您觉得更干净,可以将其移至顶层。
通过此更改,我们的 if/then
可以按照您的示例进行工作,除了它没有阻止 key3
时,它应该有。我们通过在 else
中使用 not
来解决这个问题。
{
"$schema": "http://json-schema.org/draft-07/schema",
"additionalProperties": false,
"properties": {
"key1": {
"type": "string"
},
"key2": {
"type": "string"
},
"key3": true
},
"required": ["key1"],
"allOf": [
{
"if": {
"required": ["key2"],
"properties": {
"key1": {
"const": "value1"
},
"key2": {
"const": "value2"
}
}
},
"then": {
"required": ["key3"],
"properties": {
"key3": {
"type": "string"
}
}
},
"else": {
"not": {
"required": ["key3"]
}
}
}
]
}
关于Json 架构在 if 条件上添加属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69303838/