我想编写一个带有多个子模式的单文件JSON模式定义,这些子模式可以根据负载组合。
下面的模式验证了我的模式正在使用我的示例JSON响应。(响应对象的payload.role
类型错误,以确保架构捕捉到此错误!(
为了清楚起见,我在最重要的部分减少了它。完整的工作示例可在此处找到:https://www.jsonschemavalidator.net/s/3KAaXjtg
架构
{
"$schema": "http://json-schema.org/draft-07/schema",
"$id": "http://example.com/baseSchema.json",
"type": "object",
"required": [
"payload"
],
"properties": {
"payload": {
"$id": "#/properties/payload",
"type": "object",
// reference the right schema depending on the payload child key
// if `payload.user` reference `userSchema.json`
// if `payload.users` reference `usersSchema.json`
// if `payload.*` reference `*Schema.json`
"$ref": "userSchema.json"
}
},
"definitions": {
"user": {
"$id": "http://example.com/userSchema.json",
"type": "object",
"required": [
"user"
],
"properties": {
"user": {
"type": "object",
"$ref": "userProperties.json"
}
}
},
"users": {
"$id": "http://example.com/usersSchema.json",
"type": "object",
"required": [
"users"
],
"properties": {
"users": {
"type": "array",
"items": {
"$ref": "userProperties.json"
}
}
}
},
"userProperties": {
"$id": "http://example.com/userProperties.json",
"type": "object",
"properties": {
"firstName": {
"$id": "#/properties/payload/properties/user/properties/firstName",
"type": "string"
}
}
}
}
}
响应
{
"status": {
"code": 200,
"description": "User retrieved successfully."
},
"payload": {
"user": {
"firstName": "Joe",
"lastName": "Doe",
"role": "3", // for testing reasons, this is the wrong type!
"email": "doe@example.com",
"customerID": "",
"projects": [
"AIXG5mEg6QLl9rhVSE6m",
"Bs1bHiOIqKclwwis3CNf",
"NC2OUGVZXU35FA7iwRn4"
],
"status": "Status",
"id": "c555BSZnKLdHSRYqrU5hqiQo733j13"
}
}
}
因此,我得到了一个与此响应匹配的baseSchema.json
:
{
"status": {},
"payload": {}
}
payload
由某个键(如payload.user = {}
或payload.foo = {}
(扩展,根据该键,我想用我的一个定义来扩展模式。
以下部分仅适用于密钥user
:
"properties": {
"payload": {
"$id": "#/properties/payload",
"type": "object",
// reference the right schema depending on the payload child key
// if `payload.user` reference `userSchema.json`
// if `payload.users` reference `usersSchema.json`
// if `payload.*` reference `*Schema.json`
"$ref": "userSchema.json"
}
},
我无法设置任何条件(使用allOf
、if
、else
(,这些条件将基于payload
键引用正确的子模式。
如有任何提示和帮助,我们将不胜感激。
架构和最后的演示链接。。。让我们看看我们是如何到达那里的。。。
在JSONSchema draft-07和以前的版本中,不能将$ref
与其他关键字一起使用。其他关键字将被忽略。(在您的模式http://example.com/userSchema.json
中,type
位于$ref
旁边(。幸运的是,当您在引用的模式中声明类型时,这并没有给您带来任何问题。(您可以在2019-09或更高版本中做到这一点。(
关键字if
、then
和else
的值是模式。对于要应用于实例位置的then
子模式,if
模式必须返回为有效模式。如果失败,将应用else
子模式值。
我们的if条件检查是否存在特定密钥。如果密钥存在,则应用引用正确模式的模式。
因为希望条件互斥,所以需要将多个条件包装在oneOf
中,并将else: false
添加到条件检查中。false
作为模式会导致验证失败。
如果你想进一步澄清以上任何一点,请告诉我。
演示:https://jsonschema.dev/s/HLniL
{
"$schema": "http://json-schema.org/draft-07/schema",
"$id": "http://example.com/baseSchema.json",
"type": "object",
"required": [
"payload"
],
"properties": {
"payload": {
"$id": "#/properties/payload",
"type": "object",
"oneOf": [
{
"if": {
"required": [
"user"
]
},
"then": {
"$ref": "userSchema.json"
},
"else": false
},
{
"if": {
"required": [
"users"
]
},
"then": {
"$ref": "usersSchema.json"
},
"else": false
}
]
}
},
"definitions": {
"user": {
"$id": "http://example.com/userSchema.json",
"type": "object",
"required": [
"user"
],
"properties": {
"user": {
"$ref": "userProperties.json"
}
}
},
"users": {
"$id": "http://example.com/usersSchema.json",
"type": "object",
"required": [
"users"
],
"properties": {
"users": {
"type": "array",
"items": {
"$ref": "userProperties.json"
}
}
}
},
"userProperties": {
"$id": "http://example.com/userProperties.json",
"type": "object",
"properties": {
"firstName": {
"type": "string"
}
}
}
}
}