Как проверить конкретную 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 существует внутри сообщения?


person Alireza    schedule 05.06.2018    source источник


Ответы (1)


Вы можете это сделать, но это сложно. При этом используется концепция логической логики, называемая импликацией, чтобы гарантировать, что если схема 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"] }
      }
    }
  }
}
person Jason Desrosiers    schedule 08.06.2018