有条件地需要 jsonSchema 属性

在 jsonSchema 中,您可以指出定义的字段是强制性的,还是不使用“必需”属性:

{
"$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"
]
}

在某些情况下,我希望 讯息版本字段不是强制性的。有没有办法使这个字段的强制性成为条件的?

97216 次浏览

根据您的情况,有几种不同的方法。我可以想到四种不同的方式来有条件地需要一个字段。

依赖性

dependentSchemas关键字是应用模式的条件方法。在 dependentSchemas中的 Foreach 属性中,如果该属性存在于正在验证的 JSON 中,则与该键关联的架构也必须是有效的。如果存在“ foo”属性,则需要“ bar”属性

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

如果所有依赖模式都需要 required关键字,则可以使用 dependentRequired关键字作为速记。下面的示例与前面的示例具有相同的效果。

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

注意: 在草案 -07和以下这些是一个关键字称为 dependencies。如果该值是一个模式,则其行为类似于 dependentSchemas。如果该值是一个数组,则其行为类似于 dependentRequired

暗示

如果条件依赖于字段的值,则可以使用名为蕴涵的布尔逻辑概念。“ A 意味着 B”实际上意味着,如果 A 是真的,那么 B 也一定是真的。含义也可以表达为“ !”!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验证成功。

注意: if/then关键字具有相同的行为,但更容易阅读和维护。建议只在使用不支持 if/then的旧版 JSON Schema 时使用这种方法。

Enum

如果你的条件是基于一个枚举,它是一个更直接一点

{
"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"]
}
]
}

注意: 不建议使用此方法,因为它可能产生混淆的错误消息。if/then关键字通常是一种更好的方法。

如果,然后,其他

ifthenelse关键字是上面描述的含义模式的简写。这些关键词是在草案 -07中添加的。如果“ foo”属性等于“ bar”,则需要“ bar”属性

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

EDIT 12/23/2017: 含义部分更新,If-Then-Else 部分增加。

编辑06/04/2018: 修复 If-Then-Else 并更新单例 enum使用 const

编辑07/06/2022: 更新依赖项部分使用新的 dependentSchemas/dependentRequired关键字而不是 dependencies

截至2022年,dependencies被否决了,并分裂成 dependentRequired(见例如 这个例子)和 dependentSchemas(见例如 这个例子)。只要使用 dependentRequired就可以解决这个问题:

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

找到了解决办法。 使用 全部对我有用。 只是使用了差异依赖关系。

用于 draft07模式的正确方法是:

<dependency>
<groupId>com.github.erosb</groupId>
<artifactId>everit-json-schema-jdk6</artifactId>
<version>1.9.2</version>
</dependency>