Skip to content

Commit c931686

Browse files
committed
update proposal for separate ADR
1 parent 6be47fa commit c931686

File tree

1 file changed

+38
-144
lines changed

1 file changed

+38
-144
lines changed

proposals/propertyDependencies.md

Lines changed: 38 additions & 144 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,11 @@
1-
# JSON Schema: The `propertyDependencies` Keyword
1+
# JSON Schema Proposal: The `propertyDependencies` Keyword
22

33
## Abstract
44

55
The `propertyDependencies` keyword is a more friendly way to select between two
66
or more schemas to validate an instance against than is currently supported by
77
JSON Schema.
88

9-
## Status
10-
11-
**Current Status**: PROPOSAL
12-
13-
TODO: We should have a short standard blurb outlining the stages involved in a
14-
feature making its way to stable status.
15-
16-
TODO: Link to a document that describes the proposal => stable process in
17-
detail.
18-
199
## Note to Readers
2010

2111
The issues list for this document can be found at
@@ -36,24 +26,25 @@ specification](../jsonschema-core.html) also apply to this document.
3626
## Overview
3727

3828
### Problem Statement
29+
3930
A common need in JSON Schema is to select between one schema or another to
4031
validate an instance based on the value of some property in the JSON instance.
4132
There are a several patterns people use to accomplish this, but they all have
4233
significant [problems](#problems).
4334

4435
OpenAPI solves this problem with the `discriminator` keyword. However, their
4536
approach is more oriented toward code generation concerns, is poorly specified
46-
when it comes to validation, and is couple to OpenAPI concepts that don't exist
37+
when it comes to validation, and is coupled to OpenAPI concepts that don't exist
4738
is JSON Schema. Therefore, it's necessary to define something new rather than
48-
adopt `discriminator`.
39+
adopt or redefine `discriminator`.
4940

5041
### Solution
5142

5243
The `dependentSchemas` keyword is very close to what is needed except it checks
5344
for the presence of a property rather than it's value. The chosen solution is to
5445
build on that concept to solve this problem.
5546

56-
```jsonschema
47+
```json
5748
{
5849
"propertyDependencies": {
5950
"foo": {
@@ -65,7 +56,7 @@ build on that concept to solve this problem.
6556

6657
The validation result is equivalent to the following schema.
6758

68-
```jsonschema
59+
```json
6960
{
7061
"if": {
7162
"properties": {
@@ -87,26 +78,38 @@ actually use it rather than fallback to `oneOf` because it's simple. Achieving
8778
those goals means that some trade-offs need to be made. {{alternatives}} lists
8879
some alternatives that we considered.
8980

90-
## A Vocabulary for Applying Subschemas
91-
92-
This document adds the `propertyDependencies` keyword to the
93-
`https://json-schema.org/vocab/applicator` [applicator
94-
vocabulary](../jsonschema-core.html#applicatorvocab).
95-
96-
### `propertyDependencies`
97-
98-
This keyword specifies subschemas that are evaluated if the instance is an
99-
object and contains a certain property with a certain string value.
100-
101-
This keyword's value MUST be an object. Each value in the object MUST be an
102-
object whose values MUST be valid JSON Schemas.
103-
104-
If the outer object key is a property in the instance and the inner object key
105-
is equal to the value of that property, the entire instance must validate
106-
against the schema. Its use is dependent on the presence and value of the
107-
property.
108-
109-
Omitting this keyword has the same behavior as an empty object.
81+
## Change Description
82+
83+
1. The following will be added to the JSON Schema Core specification as a
84+
subsection of "Keywords for Applying Subschemas Conditionally".
85+
> ### `propertyDependencies`
86+
>
87+
> This keyword specifies subschemas that are evaluated if the instance is an
88+
> object and contains a certain property with a certain string value.
89+
>
90+
> This keyword's value MUST be an object. Each value in the object MUST be an
91+
> object whose values MUST be valid JSON Schemas.
92+
>
93+
> If the outer object key is a property in the instance and the inner object key
94+
> is equal to the value of that property, the entire instance must validate
95+
> against the schema. Its use is dependent on the presence and value of the
96+
> property.
97+
>
98+
> Omitting this keyword has the same behavior as an empty object.
99+
2. The following subschema will be added to the Applicator Vocabulary schema, `https://json-schema.org/<version>/<release>/meta/applicator` at `/properties/propertyDependencies`:
100+
```json
101+
{
102+
"type": "object",
103+
"additionalProperties": {
104+
"type": "object",
105+
"additionalProperties": {
106+
"$dynamicRef": "#meta",
107+
"default": true
108+
},
109+
"default": {}
110+
}
111+
}
112+
```
110113

111114
## [Appendix] Problems With Existing Patterns {#problems}
112115

@@ -172,115 +175,6 @@ avoid it.
172175
}
173176
```
174177

175-
## [Appendix] Alternatives Considered {#alternatives}
176-
177-
Here are some alternatives that were considered that support all value types.
178-
All examples have the same validation behavior as the examples above.
179-
180-
This version uses an array of objects. Each object is a collection of the
181-
variables needed to express a property dependency. This doesn't fit the style of
182-
JSON Schema. There aren't any keywords remotely like this. It's also still too
183-
verbose. It's a little more intuitive than `if`/`then` and definitely less error
184-
prone.
185-
186-
```jsonschema
187-
{
188-
"propertyDependencies": [
189-
{
190-
"propertyName": "foo",
191-
"propertySchema": { "const": "aaa" },
192-
"apply": { "$ref": "#/$defs/foo-aaa" }
193-
},
194-
{
195-
"propertyName": "foo",
196-
"propertySchema": { "const": "bbb" },
197-
"apply": { "$ref": "#/$defs/foo-bbb" }
198-
}
199-
]
200-
}
201-
```
202-
203-
A slight variation on that example is to make it a map of keyword to dependency
204-
object. It's still too verbose.
205-
206-
```jsonschema
207-
{
208-
"propertyDependencies": {
209-
"foo": [
210-
{
211-
"propertySchema": { "const": "aaa" },
212-
"apply": { "$ref": "#/$defs/foo-aaa" }
213-
},
214-
{
215-
"propertySchema": { "const": "bbb" },
216-
"apply": { "$ref": "#/$defs/foo-bbb" }
217-
}
218-
]
219-
}
220-
}
221-
```
222-
223-
This one is a little more consistent with the JSON Schema style (poor keyword
224-
naming aside), but otherwise has all the same problems as the other examples.
225-
226-
```jsonschema
227-
{
228-
"allOf": [
229-
{
230-
"propertyDependencyName": "foo",
231-
"propertyDependencySchema": { "const": "aaa" },
232-
"propertyDependencyApply": { "$ref": "#/$defs/foo-aaa" }
233-
},
234-
{
235-
"propertyDependencyName": "foo",
236-
"propertyDependencySchema": { "const": "bbb" },
237-
"propertyDependencyApply": { "$ref": "#/$defs/foo-bbb" }
238-
}
239-
]
240-
}
241-
```
242-
243-
This one is a variation of `if` that combines `if`, `properties`, and `required`
244-
to reduce boilerplate. It's also essentially a variation of the previous example
245-
with better names. This avoids to error proneness problem, but it's still too
246-
verbose.
247-
248-
```jsonschema
249-
{
250-
"allOf": [
251-
{
252-
"ifProperties": {
253-
"foo": { "const": "aaa" }
254-
},
255-
"then": { "$ref": "#/$defs/foo-aaa" }
256-
},
257-
{
258-
"ifProperties": {
259-
"foo": { "const": "bbb" }
260-
},
261-
"then": { "$ref": "#/$defs/foo-aaa" }
262-
}
263-
]
264-
}
265-
```
266-
267-
All of the previous alternatives use a schema as the discriminator. This
268-
alternative is a little less powerful in that it can only match on exact values,
269-
but it successfully addresses the problems we're concerned about with the
270-
current approaches. The only issue with this alternative is that it's not as
271-
intuitive as the chosen solution.
272-
273-
```jsonschema
274-
{
275-
"propertyDepenencies": {
276-
"foo": [
277-
["aaa", { "$ref": "#/$defs/foo-aaa" }],
278-
["bbb", { "$ref": "#/$defs/foo-bbb" }]
279-
]
280-
}
281-
}
282-
```
283-
284178
## [Appendix] Change Log
285179

286180
* [October 2023] Created

0 commit comments

Comments
 (0)