如何基于JSON Schema中其他属性的存在条件有条件地禁止属性? [英] How to conditionally forbid properties based on presence of other properties in JSON Schema?
问题描述
在我的架构中,我声明了以下属性:
In my schema I declared these properties:
"index_name": {
"type": "string",
"examples": ["foo-wwen-live", "foo"]
},
"locale": {
"type": "string",
"examples": ["wwen", "usen", "frfr"]
},
"environment": {
"type": "string",
"default": "live",
"examples": [
"staging",
"edgengram",
"test"
]
}
我希望针对我的模式验证的JSON正文仅在以下情况下有效:
I want a JSON body validated against my schema to be valid only if:
-
index_name
存在,并且两者locale
和environment
都不存在; -
locale
和/或enviroment
存在,而index_name
不存在
index_name
is present, and bothlocale
andenvironment
are not present;locale
and/orenviroment
are present, andindex_name
is not present
简而言之,locale
和environment
绝对不能与index_name
混用.
In short, locale
and environment
should never be mixed with index_name
.
这些应该通过:
案例#1
These should pass:
Case #1
{
"locale": "usen"
}
案例2
{
"environment": "foo"
}
案例#3
{
"environment": "foo",
"locale": "usen"
}
案例4
{
"index_name": "foo-usen"
}
这些不应该通过:
案例5
These should NOT pass:
Case #5
{
"index_name": "foo-usen",
"locale": "usen"
}
案例#6
{
"index_name": "foo-usen",
"environment": "foo"
}
案例#7
{
"index_name": "foo-usen",
"locale": "usen",
"environment": "foo"
}
我为架构创建了以下规则,但是并未涵盖所有情况.例如,如果同时存在locale
和environment
,则如果还存在index_name
,则验证将返回失败,根据情况#7,这是正确的行为.但是,如果仅存在locale
和environment
之一,则它允许同时出现index_name
(在情况5和6中失败).
I created the following rule for my schema, however it does not cover all the cases. For example, if both locale
and environment
are present, validation returns failure if index_name
is also present, which is correct behavior according to case #7. But if only one of locale
and environment
is present, it allows index_name
to also be present (fails at cases #5 and #6).
"oneOf": [
{
"required": ["index_name"],
"not": {"required": ["locale", "environment"]}
},
{
"anyOf": [
{
"required": ["locale"],
"not": {"required": ["index_name"]}
},
{
"required": ["environment"],
"not": {"required": ["index_name"]}
}
]
}
]
我对"not": {"required": []}
声明的工作方式感到困惑. 有人声称这意味着它禁止在数组中声明的任何内容都出现,这与语法给出的含义相反. 其他主张:应完全按照听起来的说法:不需要数组中列出的属性 >-它们可以出现,但是如果没有,则没关系.
I'm getting mixed information on how "not": {"required": []}
declaration works. Some people claim this means that it forbids anything declared in the array to be present, in contrary to what idea does the syntax give. Other claim that this should be taken exactly as it sounds: properties listed in the array are not required - they can be present, but it doesn't matter if they aren't.
除此规则外,我还要求在所有情况下都存在一个不相关的属性,并设置"additionalProperties": false
.
Apart from this rule, I also require one non-related property to be present in all cases and I set "additionalProperties": false
.
满足我所有测试用例的规则是什么?
What is the rule that would satisfy all my test cases?
推荐答案
依赖项
这是dependencies
关键字的工作.下面说
Dependencies
This is a job for the dependencies
keyword. The following says
- 如果存在语言环境",则禁止使用"index_name".
- 如果存在环境",则禁止使用"index_name".
|
"dependencies": {
"locale": { "not": { "required": ["index_name"] } },
"environment": { "not": { "required": ["index_name"] } }
}
not
-required
怎么了?
关于not
-required
的工作方式还有一个子问题.之所以令人困惑,是因为它并不意味着它的英文阅读方式,但是它足够相似,以至于我们有时会认为它确实如此.
What's up with not
-required
?
There's a sub question about how not
-required
works. It's confusing because it doesn't mean how it reads in English, but it's similar enough to make us think it does sometimes.
在上面的示例中,如果我们将其读为不需要",则听起来像是可选".更准确的描述是禁止".
In the above example, if we read it as "not required", it sounds like it means "optional". A more accurate description would be "forbidden".
这很尴尬,但还算不错.令人困惑的地方是您想禁止"一个以上的财产.假设我们要说的是,如果存在"foo",则禁止使用"bar"和"baz".您可能会尝试的第一件事就是这个.
That's awkward, but not too bad. Where it gets confusing is when you want to "forbid" more than one property. Let's assume we want to say, if "foo" is present, then "bar" and "baz" are forbidden. The first thing you might try is this.
"dependencies": {
"foo": { "not": { "required": ["bar", "baz"] } }
}
但是,这表示如果存在"foo",则如果同时存在"bar"和"baz",则该实例无效.他们俩都必须在那里触发失败.我们真正想要的是,如果存在"bar" OR "baz",则该参数无效.
However, what this says is that if "foo" is present, then the instance is invalid if both "bar" AND "baz" are present. They both have to be there to trigger failure. What we really wanted is for it to be invalid if "bar" OR "baz" are present.
"dependencies": {
"foo": {
"not": {
"anyOf": [
{ "required": ["bar"] },
{ "required": ["baz"] }
]
}
}
}
为什么这么难?
JSON架构针对容忍更改的架构进行了优化.模式应强制实例具有完成特定任务所需的数据.如果它有超过所需的空间,则应用程序将忽略其余部分.这样,如果将某些东西添加到实例中,则一切仍然有效.如果该实例还有一些应用程序不使用的额外字段,那么它应该不会通过验证.
Why is this so hard?
JSON Schema is optimized for schemas that are tolerant to changes. The schema should enforce that the instance has a the necessary data to accomplish a certain task. If it has more than it needs, the application ignores the rest. That way, if something is add to the instance, everything still works. It shouldn't fail validation if the instance has a few extra fields that the application doesn't use.
因此,当您尝试执行某些操作(如禁止本来可以忽略的事情)时,您会遇到一些与JSON Schema无关的事情,并且事情可能会变得有些丑陋.但是,有时这是必要的.我对您的情况不太了解,无法拨打电话,但是我猜想dependencies
在这种情况下可能是必需的,但additionalProperties
并不是必需的.
So, when you try to do something like forbidding things that you could otherwise ignore, you're going a bit against the grain of JSON Schema and things can get a little ugly. However, sometimes it's necessary. I don't know enough about your situation to make that call, but I'd guess that dependencies
is probably necessary in this case, but additionalProperties
is not.
这篇关于如何基于JSON Schema中其他属性的存在条件有条件地禁止属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!