Skip to content

Keywords for exclusive minimum/maximum #77

Closed
@handrews

Description

@handrews

This is somewhat related to the general idea of issue #55 (clearly document validation principles). One such principle is that for the most part, each schema validation keyword can be evaluated against an instance independent of the presence, absence, or value of any other keyword. This is a highly desirable property when refactoring or otherwise reasoning about complex schemas.

More formally, for nearly all validation keywords k1, k2, k3... the following holds true:

{
    "k1": "something",
    "k2": {},
    "k3": ["etc."]
}

is equivalent to

{
    "allOf": [
        {"k1": "something"},
        {"k2": {}},
        {"k3": ["etc."]}
    ]
}

There are only four exceptions:

  • minimum is controlled by exclusiveMinimum's value
  • maximum is controlled by exclusiveMaximum's value
  • additionalItems is controlled by the value of items
  • additionalProperties is controlled by the values of properties and patternProperties

The issues around additionalItems and additionalProperties are outside the scope of this issue, but I mention them as they (especially additionalProperties) are more obvious examples of the problems this sort of dependency causes. In particular, the behavior when working with allOf can be counter-intuitive.

Getting back to numeric validation, here is how minimum and maximum behave:

{
    "type": "number",
    "minimum": 0,
    "exclusiveMinimum": true,
    "maximum": 1,
    "exclusiveMaximum": true
}

is equivalent to

{
    "allOf": [
        {"type": "number"},
        {
            "minimum": 0,
            "exclusiveMinimum": true
        },
        {
            "maximum": 1,
            "exclusiveMaximum": true
        }
    ]
}

but cannot be further separated. This is particularly vexing since exclusiveMinimum and exclusiveMaximum could have been defined to take numbers like this:

{
    "type": "number",
    "exclusiveMinimum": 0,
    "exclusiveMaximum": 1
}

which now behaves nicely, being equivalent to this:

{
    "allOf": [
        {"type": "number"},
        {"exclusiveMinimum": 0},
        {"exclusiveMaximum": 1}
    ]
}

I propose that in Draft 06 we either change the value of exclusiveMinimum/exclusiveMaximum or replace them with differently named keywords that take numeric values. Migrating from Draft 05 to Draft 06 for this would be easily scriptable, as the presence of the old exclusiveMinimum or exclusiveMaximum keywords with boolean value true just means to replace the boolean with the value of minimum or maximum respectively, and remove those properties (and change the name of the "exclusive" keywords if we replace them with new names rather than changing their type).

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions