Implement an OR relationship for items that can occur in a JSON schema

51 views Asked by At

I am using jsonschema 4.17.3 with Python 3.7 to validate a JSON file. In this project I am facing a challenge, where I need to implement an OR relationship. This means in my case, that I require from 2 items that, either one of them is present, or both. This can be best explained with the JSON snippets below. Here, I want to be able to configure tasks for a tool. The first task is to download_data from a REST-API server and the second task is to upload_data the resulting (downloaded and converted data) to a relational database system. So, both tasks can occur together if I require my Python tool to do it all in one go.

{
  "tasks":{
      "download_data":{
          "targetdir": "data\\",

          "Rest":
          { 
            "type": "MyRestAPIProvider",
            "server": "MyServerName",
            "api_version": "9.99",
            "source": "production",
            "user": "de.my.corp\\User",
            "password": "!SecretPasswort!"
          }
      },
      "upload_data":{
          "zip": "",

      "database_server":{
        "host":"MyDatabaseHost",
        "port":"99999",
        "database":"MyDatabase",
        "user":"MyDatabaseUser",
        "password":"MySecretPassword"
      }
    }
  }
}

...but each task can also occur by itself alone (if I want to only download data, or only upload data that I have downloaded previously:

JSON sample to only download data:

{
  "tasks":{
      "download_data":{
          "targetdir": "data\\",

          "Rest":
          { 
            "type": "MyRestAPIProvider",
            "server": "MyServerName",
            "api_version": "9.99",
            "source": "production",
            "user": "de.my.corp\\User",
            "password": "!SecretPasswort!"
          }
      }
    }
  }
}

JSON sample to only upload data:

{
  "tasks":{
      "upload_report":{
          "zip": "",

      "database_server":{
        "host":"MyDatabaseHost",
        "port":"99999",
        "database":"MyDatabase",
        "user":"MyDatabaseUser",
        "password":"MySecretPassword"
      }
    }
  }
}

The best JSON Schema for validating this is the JSON schema shown below. Where I actually use 3 JSON Schema files of the listing below:

  1. A JSON schema containing definitions for both tasks as shown below
  2. A JSON schema containing only the definitions for the download_data task (an extract from listing below)
  3. A JSON schema containing only the definitions for the upload_data task (an extract from listing below)

Next, I try to validate a given JSON file against one of the 3 files and pronounce the JSON file valid, if it succeeded on 1., 2. or 3.

    {
      "$schema": "http://json-schema.org/draft-04/schema#",
      "type": "object",
      "properties": {
        "tasks": {
          "type": "object",
          "properties": {
            "download_data": {
              "type": "object",
              "properties": {
                "targetdir": { "type": "string" },
                "Rest": {
                  "type": "object",
                  "properties": {
                           "type": { "type": "string" },
                         "server": { "type": "string" },
                    "api_version": { "type": "string" },
                         "source": { "type": "string" },
                           "user": { "type": "string" },
                       "password": { "type": "string" }
                  }, "required": ["type", "server", "api_version", "source", "user", "password"]
                }
              },
              "required": ["targetdir", "Rest"]
            },
            "upload_data": {
              "type": "object",
              "properties": {
                "zip": { "type": "string" },
                "database_server": {
                  "type": "object",
                  "properties": {
                        "host": { "type": "string" },
                        "port": { "type": "string" },
                    "database": { "type": "string" },
                        "user": { "type": "string" },
                    "password": { "type": "string" }
                  }, "required": ["host", "port", "database", "user", "password"
                  ]
                }
              }, "required": ["zip", "database_server"]
            }
          }, "required": ["download_report", "upload_report"]
        }
      },
      "required": ["tasks"]
    }

My question is: What JSON schema representation do I need to validate this with only 1 JSON schema file, which should validate OK, if only one of the tasks is present, or both. But should fail, if there is no task present.

Bonus question: Is there a good recommended resource to find such non-trivial cases and learn from examples that might be available in a reference.

I have obviously been playing with this problem for a while before coming here. But so far, I have found only simple 101 style docs (https://json-schema.org/learn/getting-started-step-by-step) that do not seem to cover non-trivial cases like mine :-(

0

There are 0 answers