我在尝试创建一个使用oneOf和公共引用的子模式的模式时遇到了麻烦,以避免必须复制模式的某些部分。 架构应该验证的JSON如下所示:
{
"createdDate": "2015-01-20T17:10:05Z",
"createdBy": "testUser",
"lastModifiedDate": "2015-01-20T17:10:05Z",
"lastModifiedBy": "testUser",
"fileUrl": {
"path": "/path/to/file",
"fileName": "file.pdf"
},
"referenceType": "person",
"fileType": "certificate",
"personId": "12345"
}
由此,共同部分是:
{
"createdDate": "2015-01-20T17:10:05Z",
"createdBy": "testUser",
"lastModifiedDate": "2015-01-20T17:10:05Z",
"lastModifiedBy": "testUser",
"fileUrl": {
"path": "/path/to/file",
"fileName": "file.pdf"
}
}
其余3个字段的名称始终相同且都是必需的,但它们允许的枚举值会有所不同。
因此剩下的3的架构可能是以下之一:
{
"properties": {
"referenceType": {
"type": "string",
"enum": [
"vehicle"
]
},
"fileType": {
"type": "string",
"enum": [
"registration document"
]
},
"vehicleId": {
"type": "string",
"pattern": "[^ ]"
}
},
"required": [
"vehicleId"
]
}
OR
{
"properties": {
"referenceType": {
"type": "string",
"enum": [
"person"
]
},
"fileType": {
"type": "string",
"enum": [
"certificate"
]
},
"personId": {
"type": "string",
"pattern": "[^ ]"
}
},
"required": [
"personId"
]
}
我似乎无法创建一个模式,我可以避免重复公共字段,并拥有oneOf,并在整个模式中将additionalProperties设置为false。 在下面的示例中,尝试将additionalProperties设置为false会导致验证错误。是否有可能做我想做的事情?
{
"type": "object",
"$schema": "http://json-schema.org/draft-04/schema#",
"definitions": {
"commonFile": {
"properties": {
"createdDate": {
"type": "string",
"format": "date-time"
},
"createdBy": {
"type": "string",
"pattern": "[^ ]"
},
"lastModifiedDate": {
"type": "string",
"format": "date-time"
},
"lastModifiedBy": {
"type": "string",
"pattern": "[^ ]"
},
"fileUrl": {
"type": "object",
"additionalProperties": false,
"properties": {
"path": {
"type": "string",
"pattern": "[^ ]"
},
"fileName": {
"type": "string",
"pattern": "[^ ]"
}
},
"required": [
"path",
"fileName"
]
}
}
}
},
"oneOf": [{
"allOf": [
{"$ref": "#/definitions/commonFile"},
{
"properties": {
"referenceType": {
"type": "string",
"enum": [
"person"
]
},
"fileType": {
"type": "string",
"enum": [
"certificate"
]
},
"personId": {
"type": "string",
"pattern": "[^ ]"
}
},
"required": [
"personId"
]
}
]
}, {
"allOf": [
{"$ref": "#/definitions/commonFile"},
{
"properties": {
"referenceType": {
"type": "string",
"enum": [
"vehicle"
]
},
"fileType": {
"type": "string",
"enum": [
"registration document"
]
},
"vehicleId": {
"type": "string",
"pattern": "[^ ]"
}
},
"required": [
"vehicleId"
]
}
]
}
],
"required": [
"createdDate",
"createdBy",
"lastModifiedDate",
"lastModifiedBy",
"fileUrl",
"referenceType",
"fileType"
]
}
答案 0 :(得分:0)
我建议不将additionalProperties
设置为false
。通常最好只是静静地忽略未定义的属性。您需要采取以下架构来实现目标。
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"createdDate": { "type": "string", "format": "date-time" },
"createdBy": { "type": "string", "pattern": "[^ ]" },
"lastModifiedDate": { "type": "string", "format": "date-time" },
"lastModifiedBy": { "type": "string", "pattern": "[^ ]" },
"fileUrl": {
"type": "object",
"additionalProperties": false,
"properties": {
"path": { "type": "string", "pattern": "[^ ]" },
"fileName": { "type": "string", "pattern": "[^ ]" }
},
"required": ["path", "fileName"]
},
"referenceType": { "type": "string" },
"fileType": { "type": "string" },
"personId": {},
"vehicleId": {}
},
"additionalProperties": false,
"anyOf": [
{
"properties": {
"referenceType": { "enum": ["person"] },
"fileType": { "enum": ["certificate"] },
"personId": { "type": "string", "pattern": "[^ ]" }
},
"required": ["personId"],
"not" : { "required": ["vehicleId"] }
},
{
"properties": {
"referenceType": { "enum": ["vehicle"] },
"fileType": { "enum": ["registration document"] },
"vehicleId": { "type": "string", "pattern": "[^ ]" }
},
"required": ["vehicleId"],
"not" : { "required": ["personId"] }
}
],
"required": ["createdDate", "createdBy", "lastModifiedDate", "lastModifiedBy", "fileUrl", "referenceType", "fileType"]
}
我做的第一件事是删除所有无关的allOf
。只需要一个anyOf
。我在主模式中定义了公共属性。变体在anyOf
子句中描述。
如果您将additionalProperties
设置为false
,则其他架构(例如allOf
,oneOf
和anyOf
)无法引入新属性。这意味着此架构中允许的所有属性都必须包含在声明additionalProperties
为false
的架构中。这就是我在主模式中声明referenceType
,fileType
,personId
和vechicleId
的原因。
现在的问题是,当additionalProperties
为vehicleId
时,referenceType
不再排除person
personId
referenceType
vehicle
not
}。为了确保不允许这样做,我添加了referenceType
条款。
如果您添加第三个变体,限制其他属性会变得更加困难。它不只是向anyof
架构数组添加额外的referenceTypes
。您还必须向主架构添加新属性,并禁止现有additionalProperties
的所有的新类型。您必须在架构上进行更改,而不仅仅是正在更改的区域。这就是将false
设置为{{1}}通常不是最佳选择的原因。