基于枚举的 JSON Schema 切换对象属性

Posted

技术标签:

【中文标题】基于枚举的 JSON Schema 切换对象属性【英文标题】:JSON Schema switch object properties based on enum 【发布时间】: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 【参考方案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" 
      
    
  

【讨论】:

非常感谢!这是第一个构建块,但理解它对我来说很重要,这样我就可以在更深(嵌套)的级别中重用它。

以上是关于基于枚举的 JSON Schema 切换对象属性的主要内容,如果未能解决你的问题,请参考以下文章

json schema校验

使用 json-schema 来要求或禁止基于另一个属性值的属性?

具有未知属性名称的 JSON Schema

来自 JSON 或 JSON-Schema 的普通旧 Java 对象

XML Schema 如何通过枚举限制属性

枚举序列化 Json 与 XML