首页 > 解决方案 > 如何简化多个 JSON-Schema switch-like 语句

问题描述

JSON Schema 文档中有一个类似开关的条件示例。

https://json-schema.org/understanding-json-schema/reference/conditionals.html

我在示例中添加了另外两个国家/地区,它们都应具有与荷兰相同的邮政编码模式。我可以让这个示例使用两个额外的if/then结构,但是当要添加更多项目时它会变得混乱。

是否有 DRYer 版本,例如下面假设的版本?

"properties": { "country": { "const": ["Netherlands", "Upperlands", "Lowerlands" } }
{
  "type": "object",
  "properties": {
    "street_address": {
      "type": "string"
    },
    "country": {
      "enum": ["United States of America", "Canada", "Netherlands",
              "Upperlands","Lowerlands"]
    }
  },
  "allOf": [
    {
      "if": {
        "properties": { "country": { "const": "United States of America" } }
      },
      "then": {
        "properties": { "postal_code": { "pattern": "[0-9]{5}(-[0-9]{4})?" } }
      }
    },
    {
      "if": {
        "properties": { "country": { "const": "Canada" } }
      },
      "then": {
        "properties": { "postal_code": { "pattern": "[A-Z][0-9][A-Z] [0-9][A-Z][0-9]" } }
      }
    },
    {
      "if": {
        "properties": { "country": { "const": "Netherlands" } }
      },
      "then": {
        "properties": { "postal_code": { "pattern": "[0-9]{4} [A-Z]{2}" } }
      }
    }
  ]
}

标签: jsonjsonschema

解决方案


您可以改用枚举模式。它不那么冗长且易于阅读,但是您收到的错误消息很糟糕,因此我建议您坚持使用 if/then 模式。下面是使用枚举模式的样子。

{
  "type": "object",
  "properties": {
    "street_address": {
      "type": "string"
    },
    "country": {
      "enum": ["United States of America", "Canada", "Netherlands",
               "Upperlands","Lowerlands"]
    }
  },
  "anyOf": [
    {
      "properties": {
        "country": { "const": "United States of America" },
        "postal_code": { "pattern": "[0-9]{5}(-[0-9]{4})?" }
      }
    },
    {
      "properties": {
        "country": { "const": "Canada" },
        "postal_code": { "pattern": "[A-Z][0-9][A-Z] [0-9][A-Z][0-9]" }
      }
    },
    {
      "properties": {
        "country": { "const": "Netherlands" },
        "postal_code": { "pattern": "[0-9]{4} [A-Z]{2}" }
      }
    }
  ]
}

尽管没有解决冗长的好方法,但您可以采取一些措施来提高可读性/可维护性。您可以使用定义来隐藏详细的部分。

{
  "type": "object",
  "properties": {
    "street_address": {
      "type": "string"
    },
    "country": {
      "enum": ["United States of America", "Canada", "Netherlands",
               "Upperlands","Lowerlands"]
    }
  },
  "allOf": [
    { "$ref": "#/definitions/validate-us-postal-code" },
    { "$ref": "#/definitions/validate-ca-postal-code" },
    { "$ref": "#/definitions/validate-nl-postal-code" }
  ]
  "definitions": {
    "validate-us-postal-code": {
      "if": {
        "properties": { "country": { "const": "United States of America" } }
      },
      "then": {
        "properties": { "postal_code": { "pattern": "[0-9]{5}(-[0-9]{4})?" } }
      }
    },
    "validate-ca-postal-code": {
      "if": {
        "properties": { "country": { "const": "Canada" } }
      },
      "then": {
        "properties": { "postal_code": { "pattern": "[A-Z][0-9][A-Z] [0-9][A-Z][0-9]" } }
      }
    },
    "validate-nl-postal-code": {
      "if": {
        "properties": { "country": { "const": "Netherlands" } }
      },
      "then": {
        "properties": { "postal_code": { "pattern": "[0-9]{4} [A-Z]{2}" } }
      }
    }
  }
}

这使得人们能够通过阅读前几行来理解这个模式所做的一切。冗长/复杂的东西被推到底部,如果你不需要,你不必处理它。


推荐阅读