繁体   English   中英

JSON Schema - 如何应用基于 boolean 的条件并进一步限制附加属性:false?

[英]JSON Schema - How to apply conditionals based on boolean and further restrict with additionalProperties: false?

Ansible 获得了对 jsonschema 的支持,我有各种各样的用例,但大多数都需要条件。 我一直在阅读 jsonschema 和 Draft-7 if-then-else 的文档,并尝试了几种排列方式,但似乎只处理了我的目标的一半。 希望有人可以通过一个我可以解构的实际例子来帮助铺平道路。

基于“send_notifications”中的布尔值的两种可能性:

{
    "capture_state": "value here",
    "send_notifications": true,
    "user_email_list": ["email@something.com", "email2@something.com"],
    "host_info": [
        {
            "ansible_host": "192.20.xxx.xxx",
            "ECRTicket": "1103035"
        },
    .... continued
    ]
}

或者

{
    "capture_state": "value here",
    "send_notifications": false
}

本质上,仅允许和要求示例中显示的属性基于“send_notifications”中的布尔值,如果这两种模式都不是,则无条件失败。 我也可能会通过模式来改进这一点,但是这些键和类型是一个很好的开始。

我最初生成了以下基本模式以用作操作和添加条件的引用,也许它在这个模式中与使用条件和附加属性冲突:false,但是对于 jsonschema 来说,这对我来说并不是很明显,所以寻求一些帮助,这样我就可以更频繁地使用它。 任何帮助将不胜感激,感谢您抽出宝贵的时间,在堆栈上发帖的新手,如果我可以改进我的问题,请告诉我。

{
    "$schema": "http://json-schema.org/draft-07/schema",
    "type": "object",
    "required": [
        "capture_state",
        "send_notifications",
        "user_email_list",
        "host_info"
    ],
    "properties": {
        "capture_state": {
            "type": "string"
        },
        "send_notifications": {
            "type": "boolean"
        },
        "user_email_list": {
            "type": "array",
            "items": {
                "anyOf": [
                    {
                        "type": "string"
                    }
                ]
            }
        },
        "host_info": {
            "type": "array",
            "items": {
                "anyOf": [
                    {
                        "type": "object",
                        "required": [
                            "ansible_host",
                            "ECRTicket"
                        ],
                        "properties": {
                            "ansible_host": {
                                "type": "string"
                            },
                            "ECRTicket": {
                                "type": "string"
                            }
                        },
                        "additionalProperties": false
                    }
                ]
            }
        }
    },
    "additionalProperties": false
}

通常,每当您选择限制未知属性时,您都会遇到困难。 我会假设你有充分的理由,包括它是值得的。

有几种方法可以做到这一点。 我以这种方式呈现它是因为当 JSON 实例未通过模式验证时,它会产生最佳消息。

{
  "$schema": "http://json-schema.org/draft-07/schema",

  "type": "object",
  "properties": {
    "capture_state": { "type": "string" },
    "send_notifications": { "type": "boolean" },
  },
  "required": ["capture_state", "send_notifications"],

  "if": {
    "properties": {
      "send_notifications": { "const": true },
    },
    "required": ["send_notifications"]
  },
  "then": {
    "properties": {
      "capture_state": true,
      "send_notifications": true,
      "user_email_list": {
        "type": "array",
        "items": { "type": "string" }
      },
      "host_info": {
        "type": "array",
        "items": {
          "type": "object",
          "properties": {
            "ansible_host": { "type": "string" },
            "ECRTicket": { "type": "string" }
          },
          "required": ["ansible_host", "ECRTicket"],
          "additionalProperties": false
        }
      }
    },
    "required": ["user_email_list", "host_info"],
    "additionalProperties": false
  },
  "else": {
    "properties": {
      "capture_state": true,
      "send_notifications": true
    },
    "additionalProperties": false
  }
}

additionalProperties仅识别在它出现的同一子模式中声明的属性。这意味着您需要包含一些虚拟properties条目,以便它知道在模式中其他地方声明的属性。

我假设 ansible 不支持比草案 07 更新的 JSON 架构版本? 如果是这样,您可以使用unevaluatedProperties而不是additionalProperties来避免跳过您必须使用additionalProperties的一些箍。

{
  "$schema": "http://json-schema.org/draft-07/schema",

  "type": "object",
  "properties": {
    "capture_state": { "type": "string" },
    "send_notifications": { "type": "boolean" },
  },
  "required": ["capture_state", "send_notifications"],
  "unevaluatedProperties": false,

  "if": {
    "properties": {
      "send_notifications": { "const": true },
    },
    "required": ["send_notifications"]
  },
  "then": {
    "properties": {
      "user_email_list": {
        "type": "array",
        "items": { "type": "string" }
      },
      "host_info": {
        "type": "array",
        "items": {
          "type": "object",
          "properties": {
            "ansible_host": { "type": "string" },
            "ECRTicket": { "type": "string" }
          },
          "required": ["ansible_host", "ECRTicket"],
          "additionalProperties": false
        }
      }
    },
    "required": ["user_email_list", "host_info"]
  }
}

如果 Ansible 的任何人碰巧看到了这一点,那么 2020-12 草案包含unevaluatedProperties并将获得大量实现支持,因为它也包含在 OpenAPI 3.1 中。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM