Json Schema validation using If-Else - "conditionally choosing required element" not working

Hi All,
I am new to validating JSON file via JSON schema. Below is the JSON schema:

Schema
{
  "type": "object",
  "properties": {
    "Product": {
      "type": "object",
      "if": {
        "properties": {
          "Retention": {
            "type": "object"
          }
        }
      },
      "then": {
        "properties": {
          "Retention": {
            "required": [
              "AllowedRetention"
            ]
          }
        }
      },
      "else": {
        "properties": {
          "Product": {
            "required": [
              "AllowedRetention"
            ]
          }
        }
      }
    }
  }
}

I am using below JSON’s for validation against above JSON schema.

Sample JSON1
{
  "Product": {
    "Product": "Machine",
    "Retention": {
      "IsHousekeepingEnabled": false,
      "AllowedRetention": 25
    }
  }
}
Sample JSON2
{
  "Product": {
    "Process": "Machine",
    "AllowedRetention": 255
  }
}
Sample JSON 3
{
  "Product": {
    "Process": "Machine"
  }
}

Requirement:
AllowedRetention element is REQUIRED element. But this element position is different in sample JSON1 and JSON2. In absence of this element validation should fail.

JSON validation should only pass for Sample JSON1 and Sample JSON2.
But it should fail for sample JSON3.

If JSON contains “Product->Retention” then REQUIRED element is AllowedRetention which is located at “Product-> Retention → AllowedRetention” in sample JSON1.

If “Retention” element is missing as per JSON2, then REQUIRED element is AllowedRetention which sitting at Product-> AllowedRetention”.

If Retention and AllowedRetention is missing as per JSON3, then schema validation should fail.

I am using https://www.jsonschemavalidator.net/ url to validate JSON against above schema.

I am not sure Schema validation don’t go to else part, not sure IF-ELSE is the right way to handle this kind of validation.
Any inputs would be much appreciated!

Thanks

Hi @Atul,

  • In your JSON Schema you seem to accidentially nest the Product properties in the else path
  • To also “execute” the else branch when the Retention does not exist, you need to add a required: ["Retention"] to the if condition.

This should do what you need:

{
  "type": "object",
  "properties": {
    "Product": {
      "type": "object",
      "if": {
        "properties": {
          "Retention": {
            "type": "object"
          }
        },
        "required": [
          "Retention"
        ]
      },
      "then": {
        "properties": {
          "Retention": {
            "required": [
              "AllowedRetention"
            ]
          }
        }
      },
      "else": {
        "required": [
          "AllowedRetention"
        ]
      }
    }
  }
}

Note that these kind of validations are usually much easier to express and understand when modeled as a oneOf of the allowed variants instead of using if/else.


Technically this was only partially related to JSON Forms itself. So I would recommend checking the JSON Schema communities the next time :wink:

Hello,

Say, I have the next schema:

{
  "type": "object",
  "properties": {
    "entityId": {
      "type": "string",
      "title": "Entity ID"
    },
    "customKeys": {
      "type": "string",
      "title": "Keys"
    },
    "entityName": {
      "type": "string",
      "title": "Entity name",
      "minLength": 1
    },
    "primaryKey": {
      "type": "string",
      "title": "Primary key",
      "oneOf": [
        {
          "const": "Auto"
        },
        {
          "const": "Specify"
        }
      ]
    }
  },
  "required": [
    "entityName"
  ],
  "if": {
    "properties": {
      "primaryKey": {
        "const": "Specify"
      }
    }
  },
  "then": {
    "properties": {
      "customKeys": {
        "type": "string",
        "title": "Keys",
        "minLength": 1
      }
    },
    "required": [
      "customKeys"
    ]
  },
  "else": {
    "properties": {
      "entityId": {
        "type": "string",
        "title": "Entity ID",
        "minLength": 1
      }
    },
    "required": [
      "entityId"
    ]
  }
}

Assuming, if primaryKey == “Specify” it must check EntityId and EntityName, and not customKeys. Otherwise, if primaryKey == “Auto” it must check customKeys and entityName, and not entityId.

Actually, if I switch to “Auto”, type and clear “Entity ID”, then switch to “Specify” and try to apply the form it claims “Entity ID” must not have fewer than 1 characters.

What’s wrong?

Thank you!

Edward.

You are probably using an older version of JSON Forms. Up until the recent past we stored an empty string when a user emptied a text input. Only the React Material renderers additionally offered a clear button which, when used, stored undefined instead.

In your case likely an empty string was stored. I would therefore recommend upgrading to JSON Forms 3.0.0 or using a custom renderer to store undefined instead.

Hello Stefan,

Thank you for your answer. Version 3.0.0 is in use. It seems it does not switch the part of schema in full until handleChange is fired. After switching primaryKey, applying the form leads to the error. But if I additionally change some of fields and apply, it’s succeeded.

Edward.