有条件地需要jsonSchema属性


96

在jsonSchema中,您可以使用required属性指示已定义的字段是否为必需字段:

{
    "$schema": "http://json-schema.org/draft-04/schema#",
    "type": "object",
    "properties": {
        "header": {
            "type": "object",
            "properties": {
                "messageName": {
                    "type": "string"
                },
                "messageVersion": {
                    "type": "string"
                }
            },
            "required": [
                "messageName",
                "messageVersion"
            ]
        }
    },
    "required": [
        "header"
    ]
}

在某些情况下,我希望该messageVersion字段不是强制性的。有什么方法可以使此字段的强制性成为条件吗?


是的,应该有可能。数据中的哪些信息将触发强制性?
jruizaranguren

@SarveswaranMeenakshiSundaram-我不知道我只使用过json模式的v4
tom redfern

在版本3中完全可能吗?
Sarvesh

@SarveswaranMeenakshiSundaram-我不知道。试试看,让我们知道!
tom redfern

Answers:


260

根据您的情况,有几种不同的方法。我可以想到四种有条件地要求使用字段的方法。

依存关系

dependencies关键字是所述的一个条件变化required关键字。中的Foreach属性dependencies,如果该属性存在于正在验证的JSON中,则与该键关联的架构也必须有效。 如果存在“ foo”属性,则需要“ bar”属性

{
  "type": "object",
  "properties": {
    "foo": { "type": "string" },
    "bar": { "type": "string" }
  },
  "dependencies": {
    "foo": { "required": ["bar"] }
  }
}

如果架构仅包含required关键字,则还有一个简短形式。

{
  "type": "object",
  "properties": {
    "foo": { "type": "string" },
    "bar": { "type": "string" }
  },
  "dependencies": {
    "foo": ["bar"]
  }
}

意义

如果您的条件取决于字段的值,则可以使用称为蕴涵的布尔逻辑概念。“ A暗示B”有效地表示,如果A为true,则B也必须为true。含义也可以表示为“!A或B”。 “ foo”属性不等于“ bar”,或者“ bar”属性是必需的。或者,换句话说:如果“ foo”属性等于“ bar”,则“ bar”属性是必需的

{
  "type": "object",
  "properties": {
    "foo": { "type": "string" },
    "bar": { "type": "string" }
  },
  "anyOf": [
    {
      "not": {
        "properties": {
          "foo": { "const": "bar" }
        },
        "required": ["foo"]
      }
    },
    { "required": ["bar"] }
  ]
}

如果“ foo”不等于“ bar”,则#/anyOf/0匹配并验证成功。如果“ foo”等于“ bar”,则#/anyOf/0失败,并且#/anyOf/1必须有效才能使anyOf验证成功。

枚举

如果您的条件是基于枚举的,那就更简单了。 “ foo”可以是“ bar”或“ baz”。如果“ foo”等于“ bar”,则需要“ bar”。如果“ foo”等于“ baz”,则需要“ baz”。

{
  "type": "object",
  "properties": {
    "foo": { "enum": ["bar", "baz"] },
    "bar": { "type": "string" },
    "baz": { "type": "string" }
  },
  "anyOf": [
    {
      "properties": {
        "foo": { "const": "bar" }
      },
      "required": ["bar"]
    },
    {
      "properties": {
        "foo": { "const": "baz" }
      },
      "required": ["baz"]
    }
  ]
}

如果-然后-其他

一个相对较新除了JSON模式(草案-07)增加了ifthenelse关键字。 如果“ foo”属性等于“ bar”,则需要“ bar”属性

{
  "type": "object",
  "properties": {
    "foo": { "type": "string" },
    "bar": { "type": "string" }
  },
  "if": {
    "properties": {
      "foo": { "const": "bar" }
    },
    "required": ["foo"]
  },
  "then": { "required": ["bar"] }
}

编辑2017年12月23日:隐含部分已更新,而If-Then-Else部分已添加。

编辑06/04/2018: If-Then-Else的错误修正,并更新singleton enum以使用const


7
@scubbo我不喜欢这些if-then-else关键字,并且我拒绝使用它们。但是,如果您选择使用它,我建议始终将它们包装在allOf仅包含这三个关键字的中。{ ...other_keywords..., "allOf": [{ "if": ..., "then": ..., "else": ... }], ...more_keywords... }
杰森·德罗斯

2
@Jason为什么不喜欢if...?我认为在您的回答中对此有一个简短的意见是完全合理的。还是长话短说?
粘土桥'18

6
@ClayBridges评论部分不是该讨论的正确位置,但这是简短的版本。通常,JSON Schema关键字是无状态的。除关键字值外,没有其他信息可用于验证实例。ifthenelse违反此规则,因为它们彼此依赖。
杰森·德罗斯

3
@GGirard,这是我所知道的在JSON模式中使用这些模式的最佳方法。布尔运算已正式记录,但其余只是数学运算。allOf== AND,anyOf== OR,oneOf== XOR和not== NOT。您可以在“布尔代数”上搜索Google,以获取有关数学知识的更多资源(例如蕴涵)。
杰森·德罗斯

2
@AlexeyShrub我一直想写一段时间,但是被其他事情分散了注意力。我喜欢有条件的想法。它确实使人们更容易理解。我反对将其定义为三个独立的有状态关键字的方式(请参阅前面的评论)。如果关键字违反其他关键字遵循的架构属性,则将使JSON Schema验证器更难以实现且效率更低。如果条件是以无状态的另一种方式定义的,那么我将没有异议。
杰森·德罗斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.