Conditional Field Validation (Advanced)

Advanced rules and constraints on profile and relationship definition fields.

Clinia's Profiles and Relationship Definitions also provide condition validation rules for their properties. These rules (Similar to the ones exposed in the Field Validation documentation) are applied conditionally to another field's value.

Condition Validation Criteria

To specify when should a specific validation be in effect, the Clinia spec exposes a when property that can be used to refer to another field property:

{
    "properties": {
        "<propertyKey>": {
            "type": "...",
            "rules": [
                {
                    // All conditional rules
                    "when": {
                        // Specific Operators
                    }
                },
                {
                    // All conditional rules
                    "when": {
                        // Specific Operators
                    }
                },
            ]
        }
    }
}

As seen above, multiple conditional validation criteria can also be specified on a single property. Something to keep in mind is that rules are applied as soon as their when contained operator is evaluated to true.

If we take our provider for example, we can apply conditional validation rules such as "Specialities are required and must be at least one item if the Practice Number is specified":

{
    "properties": {
        "name": {
            "type": "symbol"
        },
        "practiceNumber": {
            "type": "integer"
        },
        "specialities": {
            "type": "array",
            "rules": [
                // Conditional Rule with a "when" clause
                {
                    "required": true,
                    "min": 1,
                    "when": {
                        "eq": {
                            "practiceNumber": "*" // Wildcard to test for the presence of a value
                        }
                    }
                }
            ],
            "items": {
                "type": "symbol"
            }
        }
    }
}

Allowed Operators

Property validation when clause supports three main operators to test for a condition to be filled (a subset of the operators available as Search Operators).

OperatorDescription
eqAn operation to test if the given property has the same value, or some equivalence (ex: Case insensitive for symbol type). The wildcard * can be used alone to test if the field has a value, or with text to test for partial match.
ltOnly usable on date, time or numerical fields An operation to test if a property has a value lower or equal to a given one.
gtOnly usable on date, time or numerical fields. An operation to test if a property has a value greater or equal to a given one.

Nested Object Validation

For validation in nested objects, the properties mentioned in the when clauses are built from the root of the profile.

This means that for a complex profile, you could build something like this to impose a emailCC when the contact point is of type email:

{
    "properties": {
        "details": {
            "type": "object",
            "properties": {
                "contact": {
                    "type": "contactpoint",
                    "properties": {
                        "system": {
                            "rules": [
                                {
                                    "required": true,
                                    "enum": [
                                        "phone",
                                        "fax",
                                        "email"
                                    ]
                                }
                            ]
                        }
                    }
                },
                "emailCC": {
                    "type": "symbol",
                    "rules": [
                        {
                            "required": true,
                            "when": {
                                "eq": {
                                    // Referring to the property from the root of the profile
                                    "details.contact.system": "email"
                                }
                            }
                        }
                    ]
                }
            }
        }
    }
}

Object Array Validation

Similar to the above, when using an operator on a property that is inside of an array, two choices are possible:

  1. If you want to test that ANY object/property of the array follows the clause, you can use the [*] clause (Inside or outside the array).
  2. If you want to test against another property in the same object (Property with the rule must also be in the same object), you can use the [current] clause.

This could result in profile definitions such as:

Testing for the condition: "emailCC is required if ANY contact point system is of type "email"":

{
    "properties": {
        "contacts": {
            "type": "array",
            "items": {
                "type": "contactpoint"
            },
            "emailCC": {
                "type": "symbol",
                "rules": [
                    {
                        "required": true,
                        "when": {
                            "eq": {
                                // Referring to any items in "contacts"
                                "contacts[*].system": "email"
                            }
                        }
                    }
                ]
            }
        }
    }
}

Testing for the condition: "value must be defined if the contact system value is of type "email""

{
    "properties": {
        "contacts": {
            "type": "array",
            "items": {
                "type": "contactpoint",
                "properties": {
                    "value": {
                        "rules": [
                            {
                                "required": true,
                                "when": {
                                    "eq": {
                                        // Referring to the current item in "contacts"
                                        "contacts[current].system": "email"
                                    }
                                }
                            }
                        ]
                    }
                }
            }
        }
    }
}