首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何有条件地禁止基于JSON模式中其他属性的属性?

如何有条件地禁止基于JSON模式中其他属性的属性?
EN

Stack Overflow用户
提问于 2020-04-06 12:17:54
回答 2查看 1.5K关注 0票数 11

在我的模式中,我声明了以下属性:

代码语言:javascript
复制
"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主体只有在的情况下才是有效的

  • index_name 存在的,而 localeenvironment 都不是locale和/或enviroment E 118E 219index_name E 121不是E 222当前H 223F 224

简而言之,locale和environment不应与index_name混为一谈。

测试用例和期望的结果:

这些应该通过:

案件1

代码语言:javascript
复制
{
  "locale": "usen"
}

案例2

代码语言:javascript
复制
{
  "environment": "foo"
}

案件3

代码语言:javascript
复制
{
  "environment": "foo",
  "locale": "usen"
}

案例4

代码语言:javascript
复制
{
  "index_name": "foo-usen"
}

这些不应该通过:

案例5

代码语言:javascript
复制
{
  "index_name": "foo-usen",
  "locale": "usen"
}

案例6

代码语言:javascript
复制
{
  "index_name": "foo-usen",
  "environment": "foo"
}

案例7

代码语言:javascript
复制
{
  "index_name": "foo-usen",
  "locale": "usen",
  "environment": "foo"
}

我为我的模式创建了以下规则,但是它并不涵盖所有的情况。例如,如果同时存在locale和environment,如果index_name也存在,则验证返回失败,根据案例7,这是正确的行为。但是,如果只有locale和environment中的一个存在,则允许index_name也出现(在案例#5和#6中失败)。

代码语言:javascript
复制
  "oneOf": [
    {
      "required": ["index_name"],
      "not": {"required":  ["locale", "environment"]}
    },
    {
      "anyOf": [
        {
          "required": ["locale"],
          "not": {"required": ["index_name"]}
        },
        {
          "required": ["environment"],
          "not": {"required": ["index_name"]}
        }
      ]
    }
  ]

关于"not": {"required": []}声明的工作方式,我得到的信息参差不齐。Some people声称这意味着它禁止数组中声明的任何内容存在,这与语法给出的想法相反。Other claim表示,这应该完全按照听起来的方式进行:数组中列出的属性是而不是必需的--它们可以存在,但如果不存在则无关紧要。

除此规则外,我还要求在所有情况下都有一个与此无关的属性,并设置了"additionalProperties": false。

什么规则可以满足我所有的测试用例?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-04-06 15:07:35

依赖关系

这是dependencies关键字的作业。以下所述

如果"locale“存在,则禁止

  • ,则禁止"index_name”。如果“环境”存在,则禁止
  • ,则禁止"index_name“。

|

代码语言:javascript
复制
"dependencies": {
  "locale": { "not": { "required": ["index_name"] } },
  "environment": { "not": { "required": ["index_name"] } }
}

not-required怎么了

有一个关于not-required如何工作的子问题。它令人困惑,因为它并不意味着它是如何用英语阅读的,但它的相似之处足以让我们认为它有时是这样的。

在上面的例子中,如果我们把它理解为“不需要”,它的意思似乎是“可选的”。更准确的描述将被“禁止”。

很尴尬,但也不算太糟。当你想要“禁止”一个以上的属性时,就会让人感到困惑。假设我们想说,如果"foo“存在,那么"bar”和"baz“是被禁止的。你要做的第一件事就是这个。

代码语言:javascript
复制
"dependencies": {
  "foo": { "not": { "required": ["bar", "baz"] } }
}

但是,这说明如果"foo“存在,则如果"bar”和"baz“同时存在,则实例无效。他们都必须在场才能触发失败。我们真正想要的是,如果"bar“或"baz”存在,它就无效。

代码语言:javascript
复制
"dependencies": {
  "foo": {
    "not": {
      "anyOf": [
        { "required": ["bar"] },
        { "required": ["baz"] }
      ]
    }
  }
}

为什么这么难?

JSON架构是针对允许更改的架构进行优化的。架构应该强制执行实例具有完成某项任务所需的数据。如果它有超出其需要的内容,则应用程序将忽略其余部分。这样,如果将某些内容添加到实例中,则一切都仍然有效。如果实例有一些应用程序不使用的额外字段,那么它不应该失败验证。

因此,当您尝试做一些其他可以忽略的事情,比如禁止的事情时,您会遇到一些与JSON格格不入的问题,事情可能会变得有点糟糕。然而,有时这是必要的。我对您的情况不太了解,无法打那个电话,但我猜想在这种情况下dependencies可能是必要的,但additionalProperties不是。

票数 15
EN

Stack Overflow用户

发布于 2020-04-06 14:45:44

因为required: [a, b]的意思是(a必须在场,b必须在场)

那么not: {required: [a, b]}的意思是(不是(a必须在场,b必须在场))

它在逻辑上等同于(a不能存在或b不能存在)。

所以说(a不在场,b不在场),这不是正确的表述。您需要两个not

考虑到您的要求,下面是正确的表达式:

代码语言:javascript
复制
{
  "oneOf": [
    {
      "required": ["index_name"],
      "allOf": [
        {"not": {"required": ["locale"]}},
        {"not": {"required": ["environment"]}}
      ]
    },
    {
      "anyOf": [
        {"required": ["locale"]},
        {"required": ["environment"]}
      ],
      "not": {
        "required": ["index_name"]
      }
    }
  ]
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61059683

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档