我将属性列表定义为json schema:
{
"$schema": "http://json-schema.org/schema#",
"type": "object",
"definitions": {
"attribute": {
"type": "object",
"properties": {
"symbolic-name": { "type":"string"},
"value": { "type":"string"}
},
"required": ["symbolic-name", "value"]
},
"displayname": {
"type": "object",
"properties": {
"symbolic-name": {"enum":["displayName"]},
"value": { "type":"string"}
},
"required": ["symbolic-name", "value"]
}
},
"properties": {
"attributes":{
"type": "array",
// This is the crucial point:
"items": {"oneOf": [
{"$ref": "#/definitions/attribute"},
{"$ref": "#/definitions/displayname"}
]},
"uniqueItems": true
}
}
}
我想要求列表中只有一个属性symbolic-name="displayName"
有效的数据对象是:
{
"attributes":[
{"symbolic-name": "displayName", "value": "Display Name"},
{"symbolic-name": "somethingElse", "value": "value1"}
{"symbolic-name": "somethingElse", "value": "value2"}
]
}
现在,由于displayName属性不仅匹配“oneOf”,而且两个限制都匹配,因此无法验证。我无法将其更改为“allOf”,因为displayName旁边的所有其他属性将不再匹配。
答案 0 :(得分:2)
为了使"oneOf"
能够正常工作,您需要使用"属性"和" displayname"模式是相互排斥的 - 如同书写的,任何有效的"显示名称"也是一个有效的"属性"。我们可以通过排除" displayName"作为"属性"的有效符号名称:
"symbolic-name": {
"type": "string",
"not": {"enum": ["displayName"]}
}
现在元素的符号名称为" displayName"可以匹配" displayname"定义,但永远不会匹配"属性"定义
你问题的另一部分是关于只有一个" displayname"在你的数组中。这比较棘手。它还取决于您正在使用的JSON Schema草稿。实施了4和6,并且星期一发布了7个 - 只是声明"$schema": "http://json-schema.org/schema#"
表示您使用的是最新的,即7个。我建议使用$schema
的特定草稿而不是非{ - 编号可能会更改,恕不另行通知。
如果你可以要求" displayname"要成为数组的第一个元素,那么这适用于任何草稿(你甚至不需要"oneOf"
):
"items": [{"$ref": "#/definitions/displayname"}],
"additionalItems": {"$ref": "#/definitions/attribute"}
请注意"items"
是一个数组。这意味着第一项必须是" displayname"除了第一项之外的所有其他项目必须是"属性" s。
如果你想允许" displayname"在任何位置,这都比较难。从草案06开始,有"contains"
,这需要至少一个项目来匹配给定的模式。但是没有简单的方法可以说"最多只有一个项目"。但是,建议将"minContains"
和"maxContains"
用于草案-08:https://github.com/json-schema-org/json-schema-spec/issues/441
目前,希望您可以要求第一个位置为" displayname",因为这将适用于所有草稿。