如何将 oneOf 与通用子模式 (V4) 一起使用
How to use oneOf alongside a common sub-schema (V4)
我在尝试创建同时使用 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"
]
}
或
{
"properties": {
"referenceType": {
"type": "string",
"enum": [
"person"
]
},
"fileType": {
"type": "string",
"enum": [
"certificate"
]
},
"personId": {
"type": "string",
"pattern": "[^ ]"
}
},
"required": [
"personId"
]
}
我似乎无法创建一个模式,从而避免重复公共字段,并拥有一个,并在整个模式中将 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"
]
}
我建议不要 将 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
的原因。
现在的问题是当referenceType
为person
时additionalProperties
不再排除vehicleId
或当referenceType
为[=]时排除personId
33=]。为了确保不允许这样做,我添加了 not
子句。
如果您添加第三个变体,限制其他属性会变得更加困难。它不仅仅是向 anyof
架构数组添加一个额外的 referenceType
。您还必须向主模式添加新属性,并禁止现有 referenceTypes
的 all 的这些新类型。您必须对整个架构进行更改,而不仅仅是正在更改的区域。这就是为什么将 additionalProperties
设置为 false
通常不是最好的主意。
我在尝试创建同时使用 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"
]
}
或
{
"properties": {
"referenceType": {
"type": "string",
"enum": [
"person"
]
},
"fileType": {
"type": "string",
"enum": [
"certificate"
]
},
"personId": {
"type": "string",
"pattern": "[^ ]"
}
},
"required": [
"personId"
]
}
我似乎无法创建一个模式,从而避免重复公共字段,并拥有一个,并在整个模式中将 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"
]
}
我建议不要 将 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
的原因。
现在的问题是当referenceType
为person
时additionalProperties
不再排除vehicleId
或当referenceType
为[=]时排除personId
33=]。为了确保不允许这样做,我添加了 not
子句。
如果您添加第三个变体,限制其他属性会变得更加困难。它不仅仅是向 anyof
架构数组添加一个额外的 referenceType
。您还必须向主模式添加新属性,并禁止现有 referenceTypes
的 all 的这些新类型。您必须对整个架构进行更改,而不仅仅是正在更改的区域。这就是为什么将 additionalProperties
设置为 false
通常不是最好的主意。