首页 > 解决方案 > jsonschema Draft 0.7 required properties in nested object depending on a value

问题描述

I have a json file with nested objects.

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

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

        "references":{

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

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

Now I would like to define that invoiceId and invoiceDate should be required if documentType is invoice, and also the other way arraound (creditNoteId and Date are required if documentType is creditNote). All other Properties should be optional.

Pseudo-Code:

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

If i store all properties in the same object I found this working solution:

{
  "$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"]
        }
      ]
    }
  }
}

Is there a way to display this dependency with nested objects used in the above json?

What I tried already was:

{
  "$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"
          ]
        }
      }
    }
  }
}

But with this i get an Error from https://www.jsonschemavalidator.net

Message: JSON is valid against more than one schema from 'oneOf'. Valid schema indexes: 0, 1.

What have I missed?

标签: jsonjsonschema

解决方案


在 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"
                    ]
                }
            }
        }
    }
}

推荐阅读