鉴于以下JSON和模式,actor.mbox,actor.member [0] .objectType和actor.member [0] .mbox都应该失败。他们不。我的架构中肯定有问题。我认为我已将其范围缩小到与IdGroup定义有关的内容,但我找不到问题。任何json架构大师都看到明显的错误吗?
JSON
{
"actor": {
"objectType": "Group",
"name": "Group Identified",
"mbox": "http://should.fail.com",
"member": [
{
"objectType": "Agent_shouldfail",
"name": "xAPI mbox",
"mbox": "mailto:shouldfail"
}
]
},
"verb": {
"id": "http://adlnet.gov/expapi/verbs/attended",
"display": {
"en-GB": "attended",
"en-US": "attended"
}
},
"object": {
"objectType": "Activity",
"id": "http://www.example.com/meetings/occurances/34534"
}
}
JSON模式(简化后)
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "xAPIValidator",
"description": "Validation schema for xAPI tests",
"type": "object",
"allOf": [
{
"$ref": "#/definitions/Statement"
}
],
"statements": {
"type": "array",
"items": {
"allOf": [
{
"$ref": "#/definitions/Statement"
}
]
}
},
"definitions": {
"Statement": {
"$id": "#Statement",
"additionalProperties": false,
"properties": {
"objectType": {
"type:": "string",
"enum": [
"Agent",
"Activity",
"Group",
"SubStatement",
"StatementRef"
]
},
"id": {
"allOf": [
{
"$ref": "#/definitions/uuid"
}
]
},
"timestamp": {
"allOf": [
{
"$ref": "#/definitions/timestamp"
}
]
},
"stored": {
"allOf": [
{
"$ref": "#/definitions/timestamp"
}
]
},
"version": {
"allOf": [
{
"$ref": "#/definitions/semanticVersion"
}
]
},
"actor": {
"$id": "#actor",
"allOf": [
{
"$ref": "#/definitions/allOfAgentGroup"
}
]
},
"authority": {
"allOf": [
{
"$ref": "#/definitions/allOfAgentGroup"
}
]
},
"verb": {
"$id": "#verb",
"type": "object",
"properties": {
"id": {
"allOf": [
{
"$ref": "#/definitions/URI"
}
]
},
"display": {
"type": "object",
"allOf": [
{
"$ref": "#/definitions/lang5646"
}
]
}
}
},
"object": {
"$id": "#object",
"type": "object",
"additionalProperties": true,
"properties": {
"objectType": {
"type:": "string",
"enum": [
"Activity",
"Agent",
"Group",
"SubStatement",
"StatementRef"
]
}
}
}
},
"required": [
"actor",
"verb",
"object"
]
},
"attachment": {
"properties": {
"usageType": {
"allOf": [
{
"$ref": "#/definitions/URI"
}
]
},
"display": {
"allOf": [
{
"$ref": "#/definitions/lang5646"
}
]
},
"description": {
"allOf": [
{
"$ref": "#/definitions/lang5646"
}
]
},
"contentType": {
"type": "string",
"pattern": "\\w+/[-+.\\w]+;?(\\w+.*=\\w+;?)*"
},
"length": {
"type": "integer"
},
"sha2": {
"type": "string"
},
"fileUrl": {
"allOf": [
{
"$ref": "#/definitions/URI"
}
]
}
}
},
"semanticVersion": {
"type": [
"string"
],
"pattern": "^([0-9]+)\\.([0-9]+)\\\\.([0-9]+)(?:-([0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*))?(?:\\+[0-9A-Za-z-]+)?$"
},
"Agent": {
"$id": "#Agent",
"allOf": [
{
"$ref": "#/definitions/IFI"
}
]
},
"AnonGroup": {
"$id": "#AnonGroup",
"maxProperties": 3,
"properties": {
"member": {
"type": "array",
"items": [
{
"allOf": [
{
"$ref": "#/definitions/allOfAgentGroup"
}
]
}
]
}
},
"dependencies": {
"objectType": [
"member"
]
},
"required": [
"member"
],
"not": {
"required": [
"mbox"
]
},
"not": {
"required": [
"mbox_sha1sum"
]
},
"not": {
"required": [
"openid"
]
},
"not": {
"required": [
"account"
]
}
},
"IdGroup": {
"$id": "#IdGroup",
"properties": {
"member": {
"type": "array",
"items": [
{
"allOf": [
{
"$ref": "#/definitions/allOfAgentGroup"
}
]
}
]
}
},
"allOf": [
{
"$ref": "#/definitions/IFI"
}
]
},
"allOfAgentGroup": {
"properties": {
"objectType": {
"type": "string",
"enum": [
"Agent",
"Group"
]
},
"name": {
"type": "string"
}
},
"oneOf": [
{
"if": {
"properties": {
"objectType": {
"const": "Agent"
}
}
},
"then": {
"allOf": [
{
"$ref": "#/definitions/Agent"
}
]
}
},
{
"if": {
"properties": {
"objectType": {
"const": "Group"
}
}
},
"then": {
"oneOf": [
{
"allOf": [
{
"$ref": "#/definitions/IdGroup"
}
]
},
{
"allOf": [
{
"$ref": "#/definitions/AnonGroup"
}
]
}
]
}
}
]
},
"IFI": {
"oneOf": [
{
"properties": {
"mbox": {
"allOf": [
{
"$ref": "#/definitions/mailto"
}
]
}
},
"required": [
"mbox"
]
},
{
"properties": {
"mbox_sha1sum": {
"type": "string",
"pattern": "\\b[0-9a-f]{5,40}\\b"
}
},
"required": [
"mbox_sha1sum"
]
},
{
"properties": {
"account": {
"properties": {
"homePage": {
"allOf": [
{
"$ref": "#/definitions/URI"
}
]
},
"name": {
"type": "string"
}
},
"required": [
"homePage",
"name"
]
}
},
"required": [
"account"
]
},
{
"properties": {
"openid": {
"allOf": [
{
"$ref": "#/definitions/URI"
}
]
}
},
"required": [
"openid"
]
}
]
},
"mailto": {
"type": "string",
"pattern": "(mailto:)(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])"
},
"timestamp": {
"type": "string",
"pattern": "^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(.[0-9]+)?(Z)?$"
},
"URI": {
"type": "string",
"pattern": "^(https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]"
},
"uuid": {
"type": "string",
"pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"
},
"lang5646": {
"type": "object",
"patternProperties": {
"^((?:(en-GB-oed|i-ami|i-bnn|i-default|i-enochian|i-hak|i-klingon|i-lux|i-mingo|i-navajo|i-pwn|i-tao|i-tay|i-tsu|sgn-BE-FR|sgn-BE-NL|sgn-CH-DE)|(art-lojban|cel-gaulish|no-bok|no-nyn|zh-guoyu|zh-hakka|zh-min|zh-min-nan|zh-xiang))|((?:([A-Za-z]{2,3}(-(?:[A-Za-z]{3}(-[A-Za-z]{3}){0,2}))?)|[A-Za-z]{4}|[A-Za-z]{5,8})(-(?:[A-Za-z]{4}))?(-(?:[A-Za-z]{2}|[0-9]{3}))?(-(?:[A-Za-z0-9]{5,8}|[0-9][A-Za-z0-9]{3}))*(-(?:[0-9A-WY-Za-wy-z](-[A-Za-z0-9]{2,8})+))*(-(?:x(-[A-Za-z0-9]{1,8})+))?)|(?:x(-[A-Za-z0-9]{1,8})+))$": {
"type": "string"
}
},
"additionalProperties": false
},
"lang5646string": {
"type": "string",
"pattern": "^((?:(en-GB-oed|i-ami|i-bnn|i-default|i-enochian|i-hak|i-klingon|i-lux|i-mingo|i-navajo|i-pwn|i-tao|i-tay|i-tsu|sgn-BE-FR|sgn-BE-NL|sgn-CH-DE)|(art-lojban|cel-gaulish|no-bok|no-nyn|zh-guoyu|zh-hakka|zh-min|zh-min-nan|zh-xiang))|((?:([A-Za-z]{2,3}(-(?:[A-Za-z]{3}(-[A-Za-z]{3}){0,2}))?)|[A-Za-z]{4}|[A-Za-z]{5,8})(-(?:[A-Za-z]{4}))?(-(?:[A-Za-z]{2}|[0-9]{3}))?(-(?:[A-Za-z0-9]{5,8}|[0-9][A-Za-z0-9]{3}))*(-(?:[0-9A-WY-Za-wy-z](-[A-Za-z0-9]{2,8})+))*(-(?:x(-[A-Za-z0-9]{1,8})+))?)|(?:x(-[A-Za-z0-9]{1,8})+))$"
}
}
}
答案 0 :(得分:1)
if/then/else
并不像您期望的那样工作。
在架构定义中,allOfAgentGroup
有一个oneOf
部分。
让我们看看它本身。
在应该失败的示例数据中,让我们自己也使用“ actor”对象。
模式:
{
"oneOf": [
{
"if": {
"properties": {
"objectType": {
"const": "Agent"
}
}
},
"then": false
}
},
false
]
}
实例数据:
{
"objectType": "Group",
"name": "Group Identified",
"mbox": "http://should.fail.com",
"member": [
{
"objectType": "Agent_shouldfail",
"name": "xAPI mbox",
"mbox": "mailto:shouldfail"
}
]
}
我们知道您希望oneOf
数组中的第二部分验证失败。
为了进行调试和演示,我们假设它确实失败了,然后将其更改为false
(这是一个有效的“ JSON Schema”,总是导致该分支上的验证失败)。
现在,鉴于上述架构和实例,您将希望JSON实例数据无法通过验证,对吗? 事实并非如此,并且验证通过了。
请记住,每个JSON Schema关键字都会为您的验证需求添加约束。
让我们看看if
和then
的实际用途。
if
此关键字的子模式的验证结果没有直接的 对整体验证结果的影响。而是控制哪个 评估“ then”或“ else”关键字。
已针对该关键字的子模式成功验证的实例 还必须针对“ then”关键字的子模式值有效, 如果有的话。
http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.6
好的,因此,如果if
的模式成功验证,则将应用then
中的模式。
实例数据无法通过if条件验证,因此...未应用then
中的模式,最终得到的是有效的“空模式”,这意味着{ {1}}。这导致您oneOf/0
断言验证成功,因为oneOf
通过而oneOf/0
失败。
要解决此问题,您需要将oneOf/1
添加到包含"then": false
和if
的对象中,以防止{{1 }}条件不满足。