互斥的属性组

问题描述 投票:0回答:3

假设我有一个具有四个可能属性的对象:a、b、c、d。 a 和 b 只能一起出现(即,当且仅当 b 出现时,a 才出现)。如果a和b出现,c不能出现(即a/b和c互斥)。如果 a 和 b 不出现,c 可能会出现(但不是必须)。 d 可以与 a/b、c 任意组合出现,也可以单独出现。除 a、b、c 或 d 之外,不得出现任何属性。

如何将其表达为 jsonschema?我怀疑我可以使用

oneOf
required
的某种组合,但我无法找出正确的咒语。

jsonschema
3个回答
19
投票

您可以将您的约束表述为:

  • 要么:
    "a"
    "b"
    都存在,并且
    "c"
    不存在
  • 或:
    "a"
    "b"
    均不存在。 (
    "c"
    可能存在也可能不存在)

第二点说“都不是”有点啰嗦。 在这里,我们使用

allOf
/
not
来表达它。 (注意:您不能将它们分解为单个
required
子句,因为每个子句都需要一个单独的
not
。)

{
    "oneOf": [
        {
            "required": ["a", "b"],
            "not": {"required": ["c"]}
        },
        {
            "allOf": [
                {
                    "not": {"required": ["a"]}
                },
                {
                    "not": {"required": ["b"]}
                }
            ]
        }
    ]
}

替代结构

还有另一种说法“都不是”,其实就是再次使用

oneOf
。 由于您必须通过 oneOf 子句中的
恰好一个
,因此如果其中一个条目是
{}
(通过所有内容),则所有其他选项都将被禁止。

虽然它稍微简洁一些,但阅读起来可能稍微不太直观:

{
    "oneOf": [
        {
            "required": ["a", "b"],
            "not": {"required": ["c"]}
        },
        {
            "oneOf": [
                {},
                {"required": ["a"]},
                {"required": ["b"]}
            ]
        }
    ]
}

1
投票

另一种选择是使用模式依赖项声明:

   "dependencies": {
     "c": {
       "allOf": [
       { 
         "not": { "required": [ "a" ] }
       },
       { 
         "not": { "required": [ "b" ] }
       }
     ]
     }, 
     "a": {
       "allOf": [
       { 
         "not": { "required": [ "c" ] }
       },
       { 
         "required": [ "b" ]
       }
     ]
     },
     "b": {
       "allOf": [
       { 
         "not": { "required": [ "c" ] }
       },
       { 
         "required": [ "a" ]
       }
     ]
     }
   }

0
投票

其他答案仍然有效,但在 JSON Schema 草案 7 中,有一种更清晰(尽管仍然很冗长)的方法来使用

if/then
来表达互斥属性。
if
模式针对实例进行测试,如果验证有效,则
then
模式也必须验证。因此,例如,如果您想让
before
after
属性互斥,您可以使用以下内容:

{
  "if": { "required": ["before"] },
  "then": {
    "not": {
      "required": ["after"]
    }
  }
}

由于在您的示例中,

c
a
b
互斥,因此逻辑(只是勉强)更复杂:

{
  "if": {
    "anyOf": [
      {"required": ["a"]},
      {"required": ["b"]}
    ]
  },
  "then": {
    "required": ["a", "b"],
    "not": {
      "required": ["c"]
    }
  }
}

您可以将其解释为指定 如果指定了 a 或 b,则必须指定 a 和 b,并且不得指定 c。

© www.soinside.com 2019 - 2024. All rights reserved.