JSON Schema (v04) anyOf with dependencies

Viewed 210

I have a JSON that can have either an IBAN account number, in which case a BIC is required, or an account_number or both of them.

So, this is valid (only account_number):

"bankaccount_data": [
    {
        "bic": null,
        "iban": null,
        "account_name": "Bankgiro",
        "account_number": "12345-6789",
        "bank_name": "Bankgiro",
        "type": "Bankgiro"
    }
]

And this is valid with iban and bic:

"bankaccount_data": [
    {
        "bic": "BANKBIC",
        "iban": "SE0123456789",
        "account_name": "Bankgiro",
        "account_number": null,
        "bank_name": "Bankgiro",
        "type": "Bankgiro"
    }
]

Even this with both account_number and iban/bic:

"bankaccount_data": [
    {
        "bic": "BANKBIC",
        "iban": "SE0123456789",
        "account_name": "Bankgiro",
        "account_number": "12345-6789",
        "bank_name": "Bankgiro",
        "type": "Bankgiro"
    }
]

My problem is with requiring BOTH iban and bic if either/or exists. I have this schema which is not doing that but should "illustrate" my need:

"bankaccount_data": {
  "type": "array",
  "items": [
    {
      "type": "object",
      "properties": {
        "account_name": { "type": "string" },
        "bank_name": { "type": [ "string", "null" ] },
        "type": { "type": "string" }
      },
      "required": [ "type" ],
      "anyOf": [
        {
          "type": "object",
          "properties": {
            "bic":   { "type": "string" },
            "iban": { "type": "string" }
          },
          "required": [ "bic", "iban" ],
          "dependencies": {
              "iban": [
                  "bic"
              ],
              "bic": [
                "iban"
            ]
          }
        },
        {
          "type": "object",
          "properties": {
            "account_number":   { "type": "string" }
          },
          "required": [ "account_number" ]
        }
      ]
    }
  ]
}
1 Answers

I wasn't quite sure, but I think you're asking for, if iban or bic is present, then the other must also be present.

You had the right ideas here. However it's complicated by the fact that your values can be null as opposed to simply not present.

dependencies only checks the properties are present, not anything to do with their value. null is still a value. dependencies cannot help you in your situation, as you always expect the keys to be present in the object.

First let's look at the solution.

{
  "anyOf": [
    {
      "properties": {
        "bic":   { "type": "string" },
        "iban": { "type": "string" },
        "account_number": { "enum": [null]}
      },
      "required": [
        "iban",
        "bic"
      ]
    },
    {
      "required": [
        "account_number"
      ],
      "properties": {
        "bic":   { "enum": [null] },
        "iban": { "enum": [null] },
        "account_number": { "type": "string" }
      }
    }
  ]
}

https://jsonschema.dev/s/dg0CY

The reason you need this sort of duplication, is you need to fully express the condition that your checking.

The values of an anyOf array are subschemas. The values are full schemas on their own.

Taking your values for anyOf, anyOf[0] does express the constraint that your looking for, however anyOf[1] says nothing about iban or bic, and so "any of" the schemas is considered valid. Each value in anyOf is not aware of the contense of the other; only the results are combined.

JSON Schema is constraints based, so anything NOT expressed, is allowed.

In the solution I've provided above, each schema in anyOf checks fully for the required condition.

For your example, it works in draft-07 the same as draft-04, so the demo is the same.

Related