如何制作除一个之外的一组互斥属性

时间:2014-06-20 14:55:12

标签: json jsonschema

我有一个遗留API我试图在JSON Schema中定义,并且该对象有一个奇怪的结构,其中有一组4个属性,其中任何一个都是必需的,其中3个是互斥的。之后是超过30个共享的可选属性,我会将它们记录为...

如,

{ "foo": "bar", "baz": 1234, ... }  // OK
{ "foo": "bar", "buzz": 1234, ... } // OK
{ "foo": "bar", "fizz": 1234, ... } // OK
{ "foo": 1234, ... }                // OK
{ "baz": 1234, ... }                // OK
{ ... }                             // NOT OK
{ "baz": 1234, "buzz": 1234, ... }  // NOT OK

我可以执行oneOf但不允许foo与其他人一起出现,anyOf允许bazbuzzfizz相互存在,这是不可能的。

我尝试定义如下内容:

{
    "type": "object",
    "properties": {
        "foo": {"type": "string"},
        "baz": {"type": "number"},
        "buzz": {"type": "number"},
        "fizz": {"type": "number"}
    },
    "anyOf": [
        {"required": ["foo"]},
        {"required": [{"oneOf": [
                {"required": ["baz"]},
                {"required": ["buzz"]},
                {"required": ["fizz"]}
            ]}
        ]}            
    ]
}

{
    "type": "object",
    "properties": {
        "foo": {"type": "string"},
        "baz": {"type": "number"},
        "buzz": {"type": "number"},
        "fizz": {"type": "number"}
    },
    "anyOf": [
        {"required": ["foo"]},
        {"oneOf": [
                {"required": ["baz"]},
                {"required": ["buzz"]},
                {"required": ["fizz"]}
            ]
        }            
    ]
}

但这不起作用,我只是不了解json架构还知道这是否可行。

2 个答案:

答案 0 :(得分:16)

有趣!可能有一个更简洁的解决方案,但我们在这里......

“互斥”约束可以通过禁止属性的成对组合来表达:

{
    "not": {
        "anyOf": [
            {"required": ["baz", "buzz"]},
            {"required": ["buzz", "fizz"]},
            {"required": ["fizz", "baz"]}
        ]
    }
}

“至少一个”约束可以用anyOf表示:

{
    "anyOf": [
        {"required": ["foo"]},
        {"required": ["baz"]},
        {"required": ["buzz"]},
        {"required": ["fizz"]}
    }
}

如果您只是将这两个约束组合到一个模式中,那么它应该可以工作:

{
    "not": {"anyOf": [...]},
    "anyOf": ...
}

答案 1 :(得分:6)

您可以使用成对排除在JSON模式中使属性互斥,但这会导致组合爆炸。当你有许多互斥的属性时,这就成了一个问题。

线性解决方案的形式如下:

  • 之一:
    • property a
    • property b
    • property c
    • 不是:
      • property a
      • property b
      • property c

如果你有很多属性,这只会得到回报。

{ "oneOf": [
  { "required": ["baz"] },
  { "required": ["buzz"] },
  { "required": ["fizz"] },
  { "not":
    { "anyOf": [
      { "required": ["baz"] },
      { "required": ["buzz"] },
      { "required": ["fizz"] }
    ] }
  }
] }

将此与@ cloudfeet的答案相结合,以获得您特定问题的答案。