条件 属性 类型

Conditional property type

我如何创建一个 JSON 模式,它具有基于另一个 属性 的值的条件 属性 类型。

我有这个:

    { // Header info removed for brevity
      "definitions": {
        "payloadTypeA": {
          "type": "object",
          "properties": {
            "requestType": {"type": "string","enum": ["A1", "A2"]}},
        },
        "payloadTypeB": {
          "type": "object",
          "properties": {
            "requestType": {"type": "string","enum": ["B1","B2"]}}
        }
      },
      "type": "object",
      "properties": {
        "workload": {
          "type": "string",
          "enum": ["A","B"]
        },
        "payload": {
          "oneOf": [
            {
              "if": {"properties": {"workload": {"const": "A"}}},
              "then": {"$ref": "#/definitions/payloadTypeA"}},
            {
              "if": {"properties": {"workload": {"const": "B"}}},
              "then": {"$ref": "#/definitions/payloadTypeB"}}
          ]
        }
      }
    }

我希望它在 workload 的值为 "A" 时使用 PayloadTypeA,在 workload 为 "B" 时使用 PayloadTypeB。但是,这验证了:

{
  "workload": "B",
  "payload": {
    "requestType": "A1",
  }
}

这也验证了:

{
  "workload": "B",
  "payload": {
    "requestType": "B1",
  }
}

但这不是:

{
  "workload": "B",
  "payload": {
    "requestType": "C1",
  }
}

因此,无论工作负载的值如何,它似乎都在针对任一有效负载模式进行验证。

我有工作负载值的其他条件,所以我不能只使用普通的 if/then/else,因为我有一个很大的 if/then/else 嵌套结构,维护起来会是一场噩梦。

你有几个问题。让我们从部分架构的简化版本开始。

"properties": {
  "workload": { "enum": ["A","B"] },
  "payload": {
    "if": { "properties": { "workload": { "const": "A" } } },
    "then": { "$ref": "#/definitions/payloadTypeA" }
  }
}

当您在此处放置 if 架构时,"workload" 属性 应位于 "payload" 属性 之下,而不是顶层。如果您正在验证一个看起来像这样的结构,这将起作用。

{
  "payload": {
    "workload": "B",
    "requestType": "B1",
  }
}

要让它工作,您必须将 if/then 块拉到更高级别的模式,它可以访问 "workload" 属性.

"properties": {
  "workload": { "enum": ["A","B"] }
},
"if": { "properties": { "workload": { "const": "A" } } },
"then": { "properties": { "payload": { "$ref": "#/definitions/payloadTypeA" } } }

下一个问题是如何组合条件。将上述修复与您现在拥有的相结合,它看起来像这样。

"properties": {
  "workload": { "enum": ["A","B"] }
},
"oneOf": [
  {
    "if": { "properties": { "workload": { "const": "A" } } },
    "then": { "properties": { "payload": { "$ref": "#/definitions/payloadTypeA" } } }
  },
  {
    "if": { "properties": { "workload": { "const": "B" } } },
    "then": { "properties": { "payload": { "$ref": "#/definitions/payloadTypeB" } } }
  }
]

if 失败时,它不会使架构失败。仅当 if 通过 then 为假时,架构才会失败。所以,如果给定一个像这样的有效模式。

{
  "workload": "B",
  "payload": {
    "requestType": "B1",
  }
}
  • /oneOf/0 将通过,因为 /oneOf/0/if 失败。
  • /oneOf/1 将通过,因为 /oneOf/1/if 通过并且 /oneOf/1/then 通过。

由于两个模式都通过了,oneOf 失败了。您可以从此示例推断,只有当所有条件都通过时,模式才应该通过。只需将 oneOf 替换为 allOf 即可。

"properties": {
  "workload": { "enum": ["A","B"] }
},
"allOf": [
  {
    "if": { "properties": { "workload": { "const": "A" } } },
    "then": { "properties": { "payload": { "$ref": "#/definitions/payloadTypeA" } } }
  },
  {
    "if": { "properties": { "workload": { "const": "B" } } },
    "then": { "properties": { "payload": { "$ref": "#/definitions/payloadTypeB" } } }
  }
]