Skip to content

Proposal: Add propertyDependencies keyword (aka discriminator) #1082

Closed
@jdesrosiers

Description

@jdesrosiers

The pattern of using oneOf to describe a choice between two types has become ubiquitous.

{
  "oneOf": [
    { "$ref": "#/$defs/aaa" },
    { "$ref": "#/$defs/bbb" }
  ]
}

However, this pattern is also notorious for its many shortcomings. There is a better way to describe this kind of constraint that doesn't have all the problems of the oneOf pattern, but it's verbose, error prone, and not particularly intuitive.

{
  "allOf": [
    {
      "if": {
        "properties": {
          "foo": { "const": "aaa" }
        },
        "required": ["foo"]
      },
      "then": { "$ref": "#/$defs/foo-aaa" }
    },
    {
      "if": {
        "properties": {
          "foo": { "const": "bbb" }
        },
        "required": ["foo"]
      },
      "then": { "$ref": "#/$defs/foo-bbb" }
    }
  ]
}

OpenAPI addresses this problem with the discriminator keyword. However their approach is more oriented toward code generation concerns and is poorly specified when it comes to validation. I don't think we should adopt discriminator, but I do think we need something like it. I believe this is the thing that is generating the most questions in our community right now.

Right now, we have the dependentSchemas keyword that is very close to what is needed except it checks for the presence of a property rather than it's value. The propertyDependencies keyword builds on that concept to solve the problem.

{
  "propertyDependencies": {
    "foo": {
      "aaa": { "$ref": "#/$defs/foo-aaa" },
      "bbb": { "$ref": "#/$defs/foo-bbb" }
    }
  }
}

If the instance is an object, then for every property (name) and value of that property (value), if /propertyDependencies/{name}/{value} is defined, then the instance must be valid against the schema at that location. Compared to discriminator, this is more consistent with the style of JSON Schema keywords because it doesn't use sub-keywords like propertyName and mappings. It's also more powerful because it allows you to discriminate using more than one property.

Because of the parallels to dependencies, I chose to name it in similar way. However, dependencies is the least well known and understood keyword, so it might not be beneficial to build on that naming convention. Either way, I don't think we should call it discriminator to avoid confusion with what OpenAPI has specified.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions