diff --git a/source/reference/conditionals.rst b/source/reference/conditionals.rst index 17d32cc8..71437f7e 100644 --- a/source/reference/conditionals.rst +++ b/source/reference/conditionals.rst @@ -21,6 +21,12 @@ constructs you've probably seen in traditional programming languages. If ``if`` is valid, ``then`` must also be valid (and ``else`` is ignored.) If ``if`` is invalid, ``else`` must also be valid (and ``then`` is ignored). +If ``then`` or ``else`` is not defined, ``if`` behaves as if they have a value +of ``true``. + +If ``then`` and/or ``else`` appear in a schema without ``if``, ``then`` and +``else`` are ignored. + We can put this in the form of a truth table, showing the combinations of when ``if``, ``then``, and ``else`` are valid and the resulting validity of the entire schema: @@ -28,13 +34,11 @@ entire schema: ==== ==== ==== ============ if then else whole schema ==== ==== ==== ============ - X X - X - X X X -X -X X -X X X -X X X X +T T n/a T +T F n/a F +F n/a T T +F n/a F F + n/a n/a T ==== ==== ==== ============ For example, let's say you wanted to write a schema to handle addresses in the @@ -54,6 +58,7 @@ letters and numbers alternate. "type": "string" }, "country": { + "default": "United States of America", "enum": ["United States of America", "Canada"] } }, @@ -63,7 +68,7 @@ letters and numbers alternate. "then": { "properties": { "postal_code": { "pattern": "[0-9]{5}(-[0-9]{4})?" } } }, - "else": { + "else": { "properties": { "postal_code": { "pattern": "[A-Z][0-9][A-Z] [0-9][A-Z][0-9]" } } } } @@ -72,7 +77,12 @@ letters and numbers alternate. "street_address": "1600 Pennsylvania Avenue NW", "country": "United States of America", "postal_code": "20500" - } + } + -- + { + "street_address": "1600 Pennsylvania Avenue NW", + "postal_code": "20500" + } -- { "street_address": "24 Sussex Drive", @@ -85,6 +95,20 @@ letters and numbers alternate. "country": "Canada", "postal_code": "10000" } + --X + { + "street_address": "1600 Pennsylvania Avenue NW", + "postal_code": "K1M 1M4" + } + +.. note:: + + In this example, "country" is not a required property. Because the "if" + schema also doesn't require the "country" property, it will pass and the + "then" schema will apply. Therefore, if the "country" property is not + defined, the default behavior is to validate "postal_code" as a USA postal + code. The "default" keyword doesn't have an effect, but is nice to include + for readers of the schema to more easily recognize the default behavior. Unfortunately, this approach above doesn't scale to more than two countries. You can, however, wrap pairs of ``if`` and ``then`` inside an ``allOf`` to create @@ -102,6 +126,7 @@ to the remaining postal codes of the world. "type": "string" }, "country": { + "default": "United States of America", "enum": ["United States of America", "Canada", "Netherlands"] } }, @@ -116,7 +141,8 @@ to the remaining postal codes of the world. }, { "if": { - "properties": { "country": { "const": "Canada" } } + "properties": { "country": { "const": "Canada" } }, + "required": ["country"] }, "then": { "properties": { "postal_code": { "pattern": "[A-Z][0-9][A-Z] [0-9][A-Z][0-9]" } } @@ -124,7 +150,8 @@ to the remaining postal codes of the world. }, { "if": { - "properties": { "country": { "const": "Netherlands" } } + "properties": { "country": { "const": "Netherlands" } }, + "required": ["country"] }, "then": { "properties": { "postal_code": { "pattern": "[0-9]{4} [A-Z]{2}" } } @@ -137,7 +164,12 @@ to the remaining postal codes of the world. "street_address": "1600 Pennsylvania Avenue NW", "country": "United States of America", "postal_code": "20500" - } + } + -- + { + "street_address": "1600 Pennsylvania Avenue NW", + "postal_code": "20500" + } -- { "street_address": "24 Sussex Drive", @@ -156,5 +188,24 @@ to the remaining postal codes of the world. "country": "Canada", "postal_code": "10000" } + --X + { + "street_address": "1600 Pennsylvania Avenue NW", + "postal_code": "K1M 1M4" + } + +.. note:: + + The "required" keyword is necessary in the "if" schemas or they would all + apply if the "country" is not defined. Leaving "required" off of the + "United States of America" "if" schema makes it effectively the default if + no "country" is defined. + +.. note:: + Even if "country" was a required field, it's still recommended to have the + "required" keyword in each "if" schema. The validation result will be the + same because "required" will fail, but not including it will add noise to + error results because it will validate the "postal_code" against all three + of the "then" schemas leading to irrelevant errors.