-
-
Notifications
You must be signed in to change notification settings - Fork 322
Extract propertyDependencies
#1506
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 7 commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
cc1cbe1
unfinished proposal; add to build
gregsdennis ee65023
fix build script
gregsdennis a5f17b6
normalize header; ignore built html file
gregsdennis 19e9102
remove hints from proposal section
gregsdennis ffee0cf
Update the build process to support more files
jdesrosiers 6be47fa
Fill in missing sections of propDeps proposal and refactor
jdesrosiers c931686
update proposal for separate ADR
gregsdennis 2b5c306
Update proposals/propertyDependencies.md
gregsdennis 25aafc7
Update proposals/propertyDependencies.md
gregsdennis c566004
add propertyDependencies adr
gregsdennis 4374400
update propertyDependencies ADR
gregsdennis a48fd8d
remove redundant 'problems' appendix and link to adr; add status section
gregsdennis File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,186 @@ | ||
# JSON Schema Proposal: The `propertyDependencies` Keyword | ||
|
||
## Abstract | ||
|
||
The `propertyDependencies` keyword is a more friendly way to select between two | ||
or more schemas to validate an instance against than is currently supported by | ||
JSON Schema. | ||
|
||
## Note to Readers | ||
|
||
The issues list for this document can be found at | ||
<https://github.com/json-schema-org/json-schema-spec/issues?q=is%3Aissue+propertydependencies>. | ||
|
||
For additional information, see <https://json-schema.org/>. | ||
|
||
To provide feedback, use this issue tracker or any of the communication methods | ||
listed on the homepage. | ||
|
||
## Table of Contents | ||
|
||
## Conventions and Terminology | ||
|
||
All conventions and terms used and defined by the [JSON Schema Core | ||
specification](../jsonschema-core.html) also apply to this document. | ||
|
||
## Overview | ||
|
||
### Problem Statement | ||
|
||
A common need in JSON Schema is to select between one schema or another to | ||
validate an instance based on the value of some property in the JSON instance. | ||
There are a several patterns people use to accomplish this, but they all have | ||
significant [problems](#problems). | ||
|
||
OpenAPI solves this problem with the `discriminator` keyword. However, their | ||
approach is more oriented toward code generation concerns, is poorly specified | ||
when it comes to validation, and is coupled to OpenAPI concepts that don't exist | ||
is JSON Schema. Therefore, it's necessary to define something new rather than | ||
adopt or redefine `discriminator`. | ||
|
||
### Solution | ||
|
||
The `dependentSchemas` keyword is very close to what is needed except it checks | ||
for the presence of a property rather than it's value. The chosen solution is to | ||
build on that concept to solve this problem. | ||
|
||
```json | ||
{ | ||
"propertyDependencies": { | ||
"foo": { | ||
"aaa": { "$ref": "#/$defs/foo-aaa" } | ||
} | ||
} | ||
} | ||
``` | ||
|
||
The validation result is equivalent to the following schema. | ||
|
||
```json | ||
{ | ||
"if": { | ||
"properties": { | ||
"foo": { "const": "aaa" } | ||
}, | ||
"required": ["foo"] | ||
}, | ||
"then": { "$ref": "#/$defs/foo-aaa" } | ||
} | ||
``` | ||
|
||
### Limitations | ||
|
||
The problem of choosing an alternative based on a property value could apply for | ||
a value of any JSON type, but `propertyDependencies` only solves this problem | ||
when the value is a string. One of the main goals of this keyword is to define | ||
something that's intuitive enough and easy enough to use that people will | ||
actually use it rather than fallback to `oneOf` because it's simple. Achieving | ||
those goals means that some trade-offs need to be made. {{alternatives}} lists | ||
some alternatives that we considered. | ||
|
||
## Change Description | ||
|
||
gregsdennis marked this conversation as resolved.
Show resolved
Hide resolved
|
||
1. The following will be added to the JSON Schema Core specification as a | ||
subsection of "Keywords for Applying Subschemas Conditionally". | ||
> ### `propertyDependencies` | ||
> | ||
> This keyword specifies subschemas that are evaluated if the instance is an | ||
> object and contains a certain property with a certain string value. | ||
> | ||
> This keyword's value MUST be an object. Each value in the object MUST be an | ||
> object whose values MUST be valid JSON Schemas. | ||
> | ||
> If the outer object key is a property in the instance and the inner object key | ||
> is equal to the value of that property, the entire instance must validate | ||
> against the schema. Its use is dependent on the presence and value of the | ||
> property. | ||
> | ||
> Omitting this keyword has the same behavior as an empty object. | ||
2. The following subschema will be added to the Applicator Vocabulary schema, `https://json-schema.org/<version>/<release>/meta/applicator` at `/properties/propertyDependencies`: | ||
```json | ||
{ | ||
"type": "object", | ||
"additionalProperties": { | ||
"type": "object", | ||
"additionalProperties": { | ||
"$dynamicRef": "#meta", | ||
"default": true | ||
}, | ||
"default": {} | ||
} | ||
} | ||
``` | ||
|
||
## [Appendix] Problems With Existing Patterns {#problems} | ||
gregsdennis marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
### `oneOf`/`anyOf` | ||
|
||
The pattern of using `oneOf` to describe a choice between two schemas has become | ||
ubiquitous. | ||
|
||
```jsonschema | ||
{ | ||
"oneOf": [ | ||
{ "$ref": "#/$defs/aaa" }, | ||
{ "$ref": "#/$defs/bbb" } | ||
] | ||
} | ||
``` | ||
|
||
However, this pattern has several shortcomings. The main problem is that it | ||
tends to produce confusing error messages. Some implementations employ | ||
heuristics to guess the user's intent and provide better messaging, but that's | ||
not wide-spread or consistent behavior, nor is it expected or required from | ||
implementations. | ||
|
||
This pattern is also inefficient. Generally, there is a single value in the | ||
object that determines which alternative to chose, but the `oneOf` pattern has | ||
no way to specify what that value is and therefore needs to evaluate the entire | ||
schema. This is made worse in that every alternative needs to be fully validated | ||
to ensure that only one of the alternative passes and all the others fail. This | ||
last problem can be avoided by using `anyOf` instead, but that pattern is much | ||
less used. | ||
|
||
### `if`/`then` | ||
|
||
We can describe this kind of constraint more efficiently and with with better | ||
error messaging by using `if`/`then`. This allows the user to explicitly specify | ||
the constraint to be used to select which alternative the schema should be used | ||
to validate the schema. However, this pattern has problems of it's own. It's | ||
verbose, error prone, and not particularly intuitive, which leads most people to | ||
avoid it. | ||
|
||
```jsonschema | ||
{ | ||
"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" } | ||
} | ||
] | ||
} | ||
``` | ||
|
||
## [Appendix] Change Log | ||
|
||
* [October 2023] Created | ||
|
||
## Champions | ||
|
||
| Champion | Company | Email | URI | | ||
|----------------------------|---------|----------------------|----------------------------------| | ||
| Jason Desrosiers | Postman | <[email protected]> | <https://github.com/jdesrosiers> | |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.