Home > Software design >  Json schema with nested objects and conditionals
Json schema with nested objects and conditionals

Time:07-26

I'm trying to create a json schema for the following structure:

{
    "stages":
    {
        "STAGE1":
        {
            "stage_type" : "GSX",
            "params":
            {
                "x": "setting_x", <- x mandatory for stage type "GSX"
                "y": "setting_y"  <- y mandatory for stage type "GSX"
            }
        },

        "STAGE2":
        {
            "stage_type" : "GSZ",
            "params":
            {
                "z": "setting_z" <- z mandatory for stage type "GSZ"
            }
        }
    }
}

The idea is that "stage_type" is an enum with possible values ["GSX", "GSZ", ...]. The logic that I would like to implement is:

  • If "stage_type" == "GSX" -> require "params": {"x"} and require "params": {"y"}
  • If "stage_type" == "GSZ" -> require "params": {"z"}

I'm failing however, at implementing this logic for required properties... Here is how far I've got:

{
    "type": "object",
    "properties":
    {
        "stages":
        {
            "type": "object",
            "additionalProperties":
            {
                "type": "object",
                "properties":
                {
                    "stage_type":
                    {
                        "type": "string",
                        "enum": [ "GSX", "GSZ" ]
                    },

                    "params":
                    {
                        "type": "object",
                        "properties":
                        {
                            "x": { "type": "string" },
                            "y": { "type": "string" },
                            "z": { "type": "string" }
                        },
                        "additionalProperties": false
                    }
                },
                "required": ["stage_type", "params"],

                "allOf":
                [
                    {
                        "if":   { "properties": { "stage_type": { "enum": ["GSX"] } } },
                        "then": { "required": ["x", "y"] }
                    },
                    {
                        "if":   { "properties": { "stage_type": { "enum": ["GSZ"] } } },
                        "then": { "required": ["z"] }
                    }
                ]
            },
            "minProperties": 1,
            "uniqueItems": true
        }
    },
    "additionalProperties": false
}

I can't seem to make the nesting of the required fileds in the if-then clauses work... Help would be very much appreciated! :)

CodePudding user response:

In your original schema, the allOf is applied to the schema level at the additionalProperties of "stages". At this level the validator has no scope of the child properties defined at the "params" property. A possible solution could be:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "description": "JSON schema generated with JSONBuddy https://www.json-buddy.com",
  "type": "object",
  "definitions": {
    "params": {
      "type": "object",
      "properties": {
        "x": { "type": "string" },
        "y": { "type": "string" },
        "z": { "type": "string" }
      },
      "additionalProperties": false
    },
    "params_required_z": {
      "allOf": [
        { "$ref": "#/definitions/params" },
        { "required": [ "z" ] }
      ]
    },
    "params_required_x_y": {
      "allOf": [
        { "$ref": "#/definitions/params" },
        { "required": [ "x", "y" ] }
      ]
    }
  },
  "properties": {
    "stages": {
      "type": "object",
      "additionalProperties": {
        "type": "object",
        "properties": {
          "stage_type": {
            "type": "string",
            "enum": [ "GSX", "GSZ" ]
          }
        },
        "allOf": [
          {
            "if": {
              "properties": {
                "stage_type": {
                  "enum": [ "GSX" ]
                }
              }
            },
            "then": {
              "properties": {
                "params": {
                  "$ref": "#/definitions/params_required_x_y"
                }
              }
            }
          },
          {
            "if": {
              "properties": {
                "stage_type": {
                  "enum": [ "GSZ" ]
                }
              }
            },
            "then": {
              "properties": {
                "params": {
                  "$ref": "#/definitions/params_required_z"
                }
              }
            }
          }
        ],
        "required": [ "stage_type", "params" ]
      },
      "minProperties": 1,
      "uniqueItems": true
    }
  },
  "additionalProperties": false
}
  • Related