为什么我使用JSON Schema`allOf`关键字无法正确验证?

时间:2019-05-02 19:21:12

标签: json jsonschema xapi

我遇到了更多未正确验证的子对象(object.actor,object.verb,object.object)。在将对象模式中的if / then结构更改为if / then / else并为彼此添加假值后,我尝试查找任何空模式。我没有发现任何明显的东西。

JSON-应该失败,但不会

{
  "actor": {
    "objectType": "Agent",
    "name": "xAPI account",
    "mbox": "mailto:xapi@adlnet.gov"
  },
  "verb": {
    "id": "http://adlnet.gov/expapi/verbs/attended",
    "display": {
      "en-GB": "attended",
      "en-US": "attended"
    }
  },
  "object": {

    "objectType": "SubStatement",
    "actor": {
      "objectType": "should fail",
      "name": "xAPI mbox",
      "mbox": "mailto:should fail"
    },
    "verb": {
      "id": "http://adlnet.gov/expapi/verbs/reported",
      "display": {
        "should fail": "reported",
        "en-US": "reported"
      }
    },
    "object": {
      "objectType": "Activity",
      "id": "should fail"
    }
  }
}

JSON-仅在根级别失败;不检查子语句值。假设某个地方有空的模式。

{
  "actor": {
    "objectType": "Agent",
    "name": "xAPI account",
    "mbox": "this fails"
  },
  "verb": {
    "id": "http://adlnet.gov/expapi/verbs/attended",
    "display": {
      "this fails": "attended",
      "en-US": "attended"
    }
  },
  "object": {

    "objectType": "SubStatement",
    "actor": {
      "objectType": "should fail",
      "name": "xAPI mbox",
      "mbox": "mailto:should fail"
    },
    "verb": {
      "id": "http://adlnet.gov/expapi/verbs/reported",
      "display": {
        "should fail": "reported",
        "en-US": "reported"
      }
    },
    "object": {
      "objectType": "Activity",
      "id": "should fail"
    }
  }
}

JSON SCHEMA(剥离到骨骼)

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "xAPIValidator",
  "description": "Validation schema for xAPI tests",
  "type": "object",
  "allOf": [
    {
      "$ref": "#/definitions/Statement"
    },
    {
      "statements": [
        {
          "$ref": "#/definitions/Statement"
        }
      ]
    }
  ],
  "definitions": {
    "Statement": {
      "additionalProperties": false,
      "properties": {
        "objectType": {
          "type:": "string",
          "enum": [
            "Agent",
            "Activity",
            "Group",
            "SubStatement",
            "StatementRef"
          ]
        },
        "id": {
          "allOf": [
            {
              "$ref": "#/definitions/uuid"
            }
          ]
        },
        "actor": {
          "$id": "#actor",
          "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",
          "properties": {
            "objectType": {
              "type:": "string",
              "enum": [
                "Activity",
                "Agent",
                "Group",
                "SubStatement",
                "StatementRef"
              ]
            }
          },
          "oneOf": [
            {
              "if": {
                "properties": {
                  "objectType": {
                    "const": "SubStatement"
                  }
                }
              },
              "then": {
                "$comment": "Substatement object type",
                "allOf": [
                  {
                    "$ref": "#/definitions/Statement"
                  }
                ],
                "allOf": [
                  {
                    "not": {
                      "required": [
                        "id"
                      ]
                    }
                  },
                  {
                    "not": {
                      "required": [
                        "authority"
                      ]
                    }
                  },
                  {
                    "not": {
                      "required": [
                        "stored"
                      ]
                    }
                  },
                  {"required":["actor","verb","object"]}
                ]
              },
              "else": false
            }
          ]
        }
      },
      "required": [
        "actor",
        "verb",
        "object"
      ]
    },
    "Agent": {
      "$id": "#Agent",
      "maxProperties": 3,
      "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",
      "maxProperties": 4,
      "properties": {
        "member": {
          "type": "array",
          "items": [
            {
              "oneOf": [
                {
                  "$ref": "#/definitions/allOfAgentGroup"
                }
              ]
            }
          ]
        }
      },
      "oneOf": [
        {
          "$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"
              }
            ]
          },
          "else": false
        },
        {
          "if": {
            "properties": {
              "objectType": {
                "const": "Group"
              }
            }
          },
          "then": {
            "oneOf": [
              {
                "allOf": [
                  {
                    "$ref": "#/definitions/IdGroup"
                  }
                ]
              },
              {
                "allOf": [
                  {
                    "$ref": "#/definitions/AnonGroup"
                  }
                ]
              }
            ]
          },
          "else": false
        }
      ]
    },
    "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])+)\\])"
    },
    "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})+))$"
    }
  }
}

1 个答案:

答案 0 :(得分:0)

然后在"$id": "#object"> oneOf中,在该JSON对象中定义两次allOf

JSON中重复键的行为未定义。 通常,处理方法只是获取对象中每个键的最后一次出现。

您可以通过使用以下架构和空对象实例来查看此工作:{}

模式:

{
  "allOf": [
    false
  ],
  "allOf": [
    true
  ]
}

JSON库可能会忽略第一个allOf,而最后一个出现,从而导致始终通过验证。交换truefalse以再次确认。

每次在架构的同一对象中多次使用特定的*of关键字(或在对象中多次使用任何键)时,都需要对其进行修复。