【问题标题】:JSON Schema switch object properties based on enum基于枚举的 JSON Schema 切换对象属性
【发布时间】:2020-10-07 01:04:12
【问题描述】:

我一直在努力解决 JSON Schema 中的“切换”问题。经历了关于这个主题的几个 GitHub 和 SO 讨论,但没有找到解决方案。 我的意图是根据“id”枚举改变“有效负载”对象属性,该枚举将具有 30 个不同的映射(每个枚举“id”的“有效负载”定义)。 例如,第一个消息 json 对象将具有数量和其他属性,但出于演示目的,我们只使用一个属性 (amout):

{
"message": {
    "id": 1,
    "correlationId": "a0011e83-280e-4085-b0f1-691059aaae61",
    "payload": {
        "amount": 100
    }
}

}

第二个json:

{
"message": {
    "id": 2,
    "correlationId": "a0011e83-280e-4085-b0f1-691059aaae61",
    "payload": {
        "code": "xyz"
    }
}

}

有没有办法以这种方式构建 JSON Schema(草案 7 或任何其他)?

【问题讨论】:

  • message 架构中有一个大的oneOf 有什么问题?每个oneOf 将包括"id": { "const": 1 } 和各自的payload 模式的properties。在 SO 上也有几个例子。
  • @Carsten 所以基本上你是在提议这样的事情:{ "message": { "type": "object", "required": ["subject"], "oneOf": [ {"properties": {"subject": {"const": 1}}}, {"properties": {"payload": {"$ref": "#/definitions/payload1"}}}, {"properties": {"subject": {"const": 2}}}, {"properties": {"payload": {"$ref": "#/definitions/payload2"}}}, ], "definitions": { "payload1": { "amount": "number" }, "payload2": { "name": "string" } } } }
  • 给定的架构还不完全正确(现在很难通过电话更正),但这是大致的方向。
  • 这能回答你的问题吗? jsonSchema attribute conditionally required

标签: jsonschema


【解决方案1】:

您要求的是一个相当普遍的要求。使用 oneOf/anyOf 应该可以让你到达你想要的地方。

在备选方案互斥的情况下(由于不同的“id”值),我赞成anyOf 允许模式验证器在遇到第一个匹配的子模式时停止检查——而oneOf意味着所有其他选择不能匹配,例如在"id": 1 的情况下,验证器只需要检查anyOf 中的第一个子模式以表明它是有效的,而对于oneOf,它必须检查其他29 个以确保那些不是也有效。但是您可能会发现 oneOf 对您的架构的人类消费者来说更具表现力。

对于您的特定场景,我会设想以下架构:

{
  "type": "object",
  "required": ["message"],
  "properties": {
    "message": {
      "type": "object",
      "required": ["id", "correlationId", "payload"],
      "properties": {
        "id": { "enum": [1, 2, 3] },
        "correlationId": { "type": "string" },
        "payload": { "type": "object" }
      },
      "anyOf": [
        {
          "properties": {
            "id": { "const": 1 },
            "payload": { "$ref": "#/definitions/payload1" }
          }
        },
        {
          "properties": {
            "id": { "const": 2 },
            "payload": { "$ref": "#/definitions/payload2" }
          }
        },
        {
          "properties": {
            "id": { "const": 3 },
            "payload": { "$ref": "#/definitions/payload3" }
          }
        },
      ]
    }
  },
  "definitions": {
    "payload1": {
      "type": "object",
      "required": ["amount"],
      "properties": {
        "amount": { "type": "integer" }
      }
    },
    "payload2": {
      "type": "object",
      "required": ["code"],
      "properties": {
        "code": { "type": "string" }
      }
    },
    "payload3": {
      "type": "object",
      "required": ["foo"],
      "properties": {
        "foo": { "type": "string" }
      }
    }
  }
}

【讨论】:

  • 非常感谢!这是第一个构建块,但理解它对我来说很重要,这样我就可以在更深(嵌套)的级别中重用它。
猜你喜欢
  • 2022-01-23
  • 2018-04-18
  • 2022-12-17
  • 2020-07-19
  • 2017-03-05
  • 1970-01-01
  • 2020-11-04
  • 1970-01-01
相关资源
最近更新 更多