首页 > 解决方案 > 如何根据文档类型验证特定的 jsonschema

问题描述

我有一个用于用户新消息的 JSON 模式:

message_creation = {
    "title": "Message",
    "type": "object",
    "properties": {
        "post": {
            "oneOf": [
                {
                    "type": "object",
                    "properties": {
                        "content": {
                            "type": "string"
                        }
                    },
                    "additionalProperties": False,
                    "required": ["content"]
                },
                {
                    "type": "object",
                    "properties": {
                        "image": {
                            "type": "string"
                        }
                    },
                    "additionalProperties": False,
                    "required": ["image"]
                },
                {
                    "type": "object",
                    "properties": {
                        "video_path": {
                            "type": "string"
                        }
                    },
                    "additionalProperties": False,
                    "required": ["video"]
                }
            ]
        },
        "doc_type": {
            "type": "string",
            "enum": ["text", "image", "video"]
        }
    },
    "required": ["post", "doc_type"],
    "additionalProperties": False
}

就这么简单!有两个字段,一个是type,另一个是post。因此,如下所示的有效负载成功:

{
    "post": {
        "image": "Hey there!"
    },
    "type": "image"
}

现在的问题是,如果用户将type值设置为text我无法验证是否已经给出了文本的架构。我应该如何验证这一点?我应该如何检查type是否设置为image然后确保image存在于帖子内部?

标签: pythonschemajsonschema

解决方案


你可以做到,但它很复杂。这使用称为蕴含的布尔逻辑概念来确保如果模式 A 匹配,则模式 B 也必须匹配。

{
  "type": "object",
  "properties": {
    "post": {
      "type": "object",
      "properties": {
        "content": { "type": "string" },
        "image": { "type": "string" },
        "video_path": { "type": "string" }
      },
      "additionalProperties": false
    },
    "doc_type": {
      "type": "string",
      "enum": ["text", "image", "video"]
    }
  },
  "required": ["post", "doc_type"],
  "additionalProperties": false,
  "allOf": [
    { "$ref": "#/definitions/image-requires-post-image" },
    { "$ref": "#/definitions/text-requires-post-content" },
    { "$ref": "#/definitions/video-requires-post-video-path" }
  ],
  "definitions": {
    "image-requires-post-image": {
      "anyOf": [
        { "not": { "$ref": "#/definitions/type-image" } },
        { "$ref": "#/definitions/post-image-required" }
      ]
    },
    "type-image": {
      "properties": {
        "doc_type": { "const": "image" }
      }
    },
    "post-image-required": {
      "properties": {
        "post": { "required": ["image"] }
      }
    },
    "text-requires-post-content": {
      "anyOf": [
        { "not": { "$ref": "#/definitions/type-text" } },
        { "$ref": "#/definitions/post-content-required" }
      ]
    },
    "type-text": {
      "properties": {
        "doc_type": { "const": "text" }
      }
    },
    "post-content-required": {
      "properties": {
        "post": { "required": ["content"] }
      }
    },
    "video-requires-post-video-path": {
      "anyOf": [
        { "not": { "$ref": "#/definitions/type-video" } },
        { "$ref": "#/definitions/post-video-path-required" }
      ]
    },
    "type-video": {
      "properties": {
        "doc_type": { "const": "video" }
      }
    },
    "post-video-path-required": {
      "properties": {
        "post": { "required": ["video_path"] }
      }
    }
  }
}

推荐阅读