如何基于JSON Schema中其他属性的存在条件有条件地禁止属性? [英] How to conditionally forbid properties based on presence of other properties in JSON Schema?

查看:237
本文介绍了如何基于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 存在,并且两者 localeenvironment 都不存在
  • locale和/或enviroment 存在,而index_name 不存在
  • index_name is present, and both locale and environment are not present;
  • locale and/or enviroment are present, and index_name is not present

简而言之,localeenvironment绝对不能与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"
}

我为架构创建了以下规则,但是并未涵盖所有情况.例如,如果同时存在localeenvironment,则如果还存在index_name,则验证将返回失败,根据情况#7,这是正确的行为.但是,如果仅存在localeenvironment之一,则它允许同时出现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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆