How to conditionally set required on nested property of array type

I have this schema that is used by jsonforms.

const schema = {
  $schema: 'http://json-schema.org/draft-07/schema#',
  type: 'object',
  properties: {
    other_ubos: {
      type: 'boolean',
    },
    persons: {
      type: 'array',
      items: {
        type: 'object',
        properties: {
          name: {
            type: 'string',
            pattern: "^[-'a-zA-ZÀ-ÖØ-öø-ÿ ]+$",
          },
          function: {
            type: 'string',
            pattern: "^[-'a-zA-ZÀ-ÖØ-öø-ÿ ]+$",
          },
          email: {
            type: 'string',
            pattern: '^(.+)@(.+)$',
          },
        },
      },
    },
  },
  required: ['other_ubos'],
  if: {
    properties: {
      other_ubos: {
        const: true,
      },
    },
  },
  then: {
    required: ['persons'],
  },
};

I want to set a condition where if other_ubos is true each array item should have name``function and email required.

so basically something like this

const schema = {
  $schema: 'http://json-schema.org/draft-07/schema#',
  type: 'object',
  properties: {
    other_ubos: {
      type: 'boolean',
    },
    persons: {
      type: 'array',
      items: {
        type: 'object',
        properties: {
          name: {
            type: 'string',
            pattern: "^[-'a-zA-ZÀ-ÖØ-öø-ÿ ]+$",
          },
          function: {
            type: 'string',
            pattern: "^[-'a-zA-ZÀ-ÖØ-öø-ÿ ]+$",
          },
          email: {
            type: 'string',
            pattern: '^(.+)@(.+)$',
          },
        },
      },
    },
  },
  required: ['other_ubos'],
  if: {
    properties: {
      other_ubos: {
        const: true,
      },
    },
  },
  then: {
    required: ['persons[number].name'],
  },
};

setting required directly on

{
        type: 'object',
        properties: {
          name: {
            type: 'string',
            pattern: "^[-'a-zA-ZÀ-ÖØ-öø-ÿ ]+$",
          },
          function: {
            type: 'string',
            pattern: "^[-'a-zA-ZÀ-ÖØ-öø-ÿ ]+$",
          },
          email: {
            type: 'string',
            pattern: '^(.+)@(.+)$',
          },
        },
}

won’t have the desired effect since it will validate even if other_ubos is false

What i ended up doing is conditionally setting the whole properties object:

const schema = {
  $schema: 'http://json-schema.org/draft-07/schema#',
  type: 'object',
  properties: {
    other_ubos: {
      type: 'boolean',
    },
  },
  if: {
    properties: {
      other_ubos: {
        const: true,
      },
    },
  },
  then: {
    properties: {
      other_ubos: {
        type: 'boolean',
      },
      persons: {
        type: 'array',
        items: {
          type: 'object',
          properties: {
            name: {
              type: 'string',
              pattern: "^[-'a-zA-ZÀ-ÖØ-öø-ÿ ]+$",
            },
            function: {
              type: 'string',
              pattern: "^[-'a-zA-ZÀ-ÖØ-öø-ÿ ]+$",
            },
            email: {
              type: 'string',
              pattern: '^(.+)@(.+)$',
            },
          },
          required: ['name', 'function', 'email'],
        },
      },
    },
  },
  required: ['other_ubos'],
};

Hi @Icenwharth,

You can partially repeat yourself within JSON Schema. It doesn’t really matter as the end validation is just a union of everything specified.

So a JSON Schema for your use case might look like this:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "other_ubos": {
      "type": "boolean"
    },
    "persons": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "pattern": "^[-'a-zA-ZÀ-ÖØ-öø-ÿ ]+$"
          },
          "function": {
            "type": "string",
            "pattern": "^[-'a-zA-ZÀ-ÖØ-öø-ÿ ]+$"
          },
          "email": {
            "type": "string",
            "pattern": "^(.+)@(.+)$"
          }
        }
      }
    }
  },
  "required": [
    "other_ubos"
  ],
  "if": {
    "properties": {
      "other_ubos": {
        "const": true
      }
    }
  },
  "then": {
    "required": [
      "persons"
    ],
    "properties": {
      "persons": {
        "items": {
          "required": [
            "name",
            "function",
            "email"
          ]
        }
      }
    }
  }
}

Thank you! This is much better than mine solution!

1 Like