了解allOf在JSON模式中的工作原理

3hvapo4f  于 2023-08-08  发布在  其他
关注(0)|答案(1)|浏览(120)

我正在学习https://json-schema.org/understanding-json-schema/reference/conditionals.html的例子,但我不明白allOf在JSON Schema中是如何工作的。

{
  "$schema": "https://json-schema.org/draft/2019-09/schema",
  "type": "object",
  "properties": {
    "street_address": {
      "type": "string"
    },
    "country": {
      "default": "United States of America",
      "enum": [
        "United States of America",
        "Canada",
        "Netherlands"
      ]
    }
  },
  "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"
          }
        },
        "required": [
          "country"
        ]
      },
      "then": {
        "properties": {
          "postal_code": {
            "pattern": "[A-Z][0-9][A-Z] [0-9][A-Z][0-9]"
          }
        }
      }
    },
    {
      "if": {
        "properties": {
          "country": {
            "const": "Netherlands"
          }
        },
        "required": [
          "country"
        ]
      },
      "then": {
        "properties": {
          "postal_code": {
            "pattern": "[0-9]{4} [A-Z]{2}"
          }
        }
      }
    }
  ]
}

字符串
示例使用allOf,据我所知,文档必须对allOf数组中的所有子模式有效。给定有效的JSON文档:

{
  "street_address": "1600 Pennsylvania Avenue NW",
  "country": "United States of America",
  "postal_code": "20500"
}


它对allOf中的第一个子模式是有效的,它处理美国邮政编码,但据我所知,对第二个("Canada")和第三个("Netherlands")子模式无效,然而,JSON文档对模式是有效的。如果在本例中使用oneOf,这是有意义的,因为它对第一个子模式有效,但对其他两个子模式无效。为什么allOf在这个例子中工作?

cs7cruho

cs7cruho1#

这个特定的结构,即包含if/then s的allOf,实际上就是您所遇到的。
为了了解发生了什么,让我们只针对第二个子模式来处理这个示例。

{
  "if": {
    "properties": {
      "country": {
        "const": "Canada"
      }
    },
    "required": [
      "country"
    ]
  },
  "then": {
    "properties": {
      "postal_code": {
        "pattern": "[A-Z][0-9][A-Z] [0-9][A-Z][0-9]"
      }
    }
  }
}

字符串
子模式说“* 如果 * country属性是"Canada",那么做另一个验证。”因为它没有else,所以当它没有通过if时,就没有验证。
因此,我可以在country * 中放入任何东西,除了 * "Canada",这个子模式将通过。

{ "country": "United States of America" }
{ "country": "Netherlands" }
{ "country": "Zimbabwe" }
{ "country": "foo" }


我甚至可以完全省略country,它将通过

{ }


所有这些都通过了,因为它们不满足if条件,并且当不满足if条件时没有约束。
现在来看更大的allOf,我们看到所有的子模式都以country为中心,而country是一个不同的值,它们都没有定义else。这意味着它们是互斥的场景,因此最多只能调用then子模式中的一个。
所有子模式都通过,因为只有一个if条件得到满足。

相关问题