jsonschema Draft 0.7 嵌套对象中的必需属性取决于值

jsonschema Draft 0.7 required properties in nested object depending on a value

我有一个包含嵌套对象的 json 文件。

{
    "apiVersion":"0.0.9b",
    "apiDate":"18.01.19",

    "general":{
        "documentType": "invoice",

        "references":{

            "invoiceId":"123",
            "invoiceDate":"01.01.1970",

            "creditNoteId":"123",
            "creditNoteDate":"01.01.1970"
        }
    }
}

现在我想定义如果 documentType 是 invoice 则需要 invoiceId 和 invoiceDate,反之亦然(如果 documentType 是 creditNote 则需要 creditNoteId 和 Date)。 所有其他属性应该是可选的。

伪代码:

documentType = invoice
- required: invoiceId, invoiceDate
- optional: creditNoteId, creditNoteDate
documentType = creditNote
- required: creditNoteId, creditNoteDate
- optional: invoiceId, invoiceDate

如果我将所有属性存储在同一个对象中,我找到了这个有效的解决方案:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "required": [
    "apiVersion",
    "apiDate"
  ],
  "properties": {
    "apiVersion": {
      "type": "string",
      "description": "The version of the json file"
    },
    "apiDate": {
      "type": "string",
      "description": "The date when the json version was published"
    },
    "general": {
      "$ref": "#/definitions/general_identifiers"
    }
  },
  "definitions" : {

    "general_identifiers" : {
      "type": "object",
      "required": [
        "documentType"
      ],
      "properties": {
        "documentType": {
          "enum": [
            "invoice",
            "creditNote"
          ]
        },
        "invoiceId": {
          "type": "string"
        },
        "invoiceDate": {
          "type": "string"
        },
        "creditNoteId": {
          "type": "string"
        },
        "creditNoteDate": {
          "type": "string"
        }
      },
      "oneOf": [
        {
          "$comment": "Invoice",
          "properties": {
            "documentType": { "enum": ["invoice"] }
          },
          "required": ["invoiceId", "invoiceDate"]
        },
        {
          "$comment": "CreditNote",
          "properties": {
            "documentType": { "enum": ["creditNote"] }
          },
          "required": ["creditNoteId", "creditNoteDate"]
        }
      ]
    }
  }
}

有没有办法用上面使用的嵌套对象显示这种依赖关系json?

我已经尝试过的是:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "required": [
    "apiVersion",
    "apiDate"
  ],
  "properties": {
    "apiVersion": {
      "type": "string",
      "description": "The version of the json file"
    },
    "apiDate": {
      "type": "string",
      "description": "The date when the json version was published"
    },
    "general": {
      "$ref": "#/definitions/general_identifiers"
    },
    "references": {
      "type": "object",
      "properties": {
        "invoiceId": {
          "type": "string"
        },
        "invoiceDate": {
          "type": "string"
        },
        "creditNoteId": {
          "type": "string"
        },
        "creditNoteDate": {
          "type": "string"
        }
      },
      "oneOf": [
        {
          "$comment": "Invoice",
          "properties": {
            "documentType": { "enum": ["invoice"] }
          },
          "required": ["invoiceId", "invoiceDate"]
        },
        {
          "$comment": "CreditNote",
          "properties": {
            "documentType": { "enum": ["creditNote"] }
          },
          "required": ["creditNoteId", "creditNoteDate"]
        }
      ]
    }

  },
  "definitions" : {

    "general_identifiers" : {
      "type": "object",
      "required": [
        "documentType"
      ],
      "properties": {
        "documentType": {
          "enum": [
            "invoice",
            "creditNote"
          ]
        }
      }
    }
  }
}

但是我从 https://www.jsonschemavalidator.net

得到一个错误

消息:JSON 对来自 'oneOf' 的多个模式有效。有效的架构索引:0、1。

我错过了什么?

你非常接近。您只需要将 oneOf 拉到顶层,这样您就可以从同一架构中引用 #/properties/general#/properties/references

此外,您几乎总是希望使用 anyOf 而不是 oneOfoneOf 强制执行列表中的一个 并且只有一个 模式有效。当模式互斥时,oneOf 只是要求验证器做不必要的工作。

"anyOf": [
  {
    "properties": {
      "general": {
        "properties": {
          "documentType": { "enum": ["invoice"] }
        }
      },
      "references": {
        "required": ["invoiceId", "invoiceDate"]
      }
    }
  },
  {
    "properties": {
      "general": {
        "properties": {
          "documentType": { "enum": ["creditNote"] }
        }
      },
      "references": {
        "required": ["creditNoteId", "creditNoteDate"]
      }
    }
  }
]

在 Jason Desrosiers 的帮助下,我终于找到了嵌套 json 的解决方案。

{
    "$schema": "http://json-schema.org/draft-07/schema#",
    "type": "object",
    "required": [
        "apiVersion",
        "apiDate"
    ],
    "anyOf": [
        {
            "properties": {
                "general": {
                    "properties": {
                        "documentType": { "enum": ["invoice"] },
                        "references": {
                            "required": ["invoiceId", "invoiceDate"]
                        }
                    }
                }
            }
        },
        {
            "properties": {
                "general": {
                    "properties": {
                        "documentType": { "enum": ["creditNote"] },
                        "references": {
                            "required": ["creditNoteId", "creditNoteDate"]
                        }
                    }
                }
            }
        }
    ], 
    "properties": {
        "apiVersion": {
            "type": "string",
            "description": "The version of the json file"
        },
        "apiDate": {
            "type": "string",
            "description": "The date when the json version was published"
        },
        "general": {
            "$ref": "#/definitions/general_identifiers",
            "references": {
                "type": "object",
                "properties": {
                    "invoiceId": {
                        "type": "string"
                    },
                    "invoiceDate": {
                        "type": "string"
                    },
                    "creditNoteId": {
                        "type": "string"
                    },
                    "creditNoteDate": {
                        "type": "string"
                    }
                } 
            }
        }
    },
    "definitions" : {
        "general_identifiers" : {
            "type": "object",
            "required": [
                "documentType"
            ],
            "properties": {
                "documentType": {
                    "enum": [
                        "invoice",
                        "creditNote"
                    ]
                }
            }
        }
    }
}