Skip to content

Commit 8b4c450

Browse files
gregsdennisjdesrosiers
authored andcommitted
$dynamicRef uses plain-name
1 parent 651599f commit 8b4c450

1 file changed

Lines changed: 28 additions & 53 deletions

File tree

specs/jsonschema-core.md

Lines changed: 28 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1021,23 +1021,16 @@ just a fragment identifier not an IRI reference. To reference the "foo"
10211021
`$anchor` from the same schema resource, you would use the fragment-only IRI
10221022
`#foo`. See below for full examples.
10231023

1024-
`$dynamicAnchor` defines a different kind of fragment identifier that only has
1025-
meaning when used with `$dynamicRef`. It's not a normal fragment identifier and
1026-
therefore can't be used anywhere other than `$dynamicRef`. Normal [fragment
1027-
identifiers](https://www.rfc-editor.org/rfc/rfc3986#section-3.5) identify the
1028-
secondary resource (the subschema) while the rest of the IRI identifies the
1029-
primary resource (the schema resource). The fragment identifiers defined by
1030-
`$dynamicAnchor` are not normal fragment identifies because they identify both
1031-
the primary resource and the secondary resource. See {{dynamic-ref}} for
1032-
details.
1024+
`$dynamicAnchor` defines a (non-fragment) identifier that only has meaning when
1025+
used with `$dynamicRef`.
10331026

10341027
If present, the value of these keywords MUST be a string and MUST conform to the
10351028
plain name fragment identifier syntax defined in {{fragments}}.
10361029

1037-
`$anchor`, `$dynamicAnchor`, and any extensions that define a plain name
1038-
fragment identifiers MUST match XML's [`NCName`
1039-
production](https://www.w3.org/TR/2006/REC-xml-names11-20060816/#NT-NCName). For
1040-
convenience, the `NCName` syntax is reproduced here in ABNF form, using a
1030+
`$anchor`, `$dynamicAnchor`, and any extensions that define plain name
1031+
fragment identifiers MUST match XML's
1032+
[`NCName` production](https://www.w3.org/TR/2006/REC-xml-names11-20060816/#NT-NCName).
1033+
For convenience, the `NCName` syntax is reproduced here in ABNF form, using a
10411034
minimal set of rules:
10421035

10431036
```abnf
@@ -1057,9 +1050,9 @@ NCNameChar = NCNameStartChar / "-" / "." / DIGIT
10571050

10581051
A schema MAY (and likely will) have multiple IRIs, but there is no way for an
10591052
IRI to identify more than one schema. When multiple schemas attempt to identify
1060-
as the same IRI through the use of `$id`, `$anchor`, `$dynamicAnchor`, or any
1061-
other mechanism, implementations SHOULD raise an error condition. Otherwise the
1062-
result is undefined, and even if documented will not be interoperable.
1053+
as the same IRI through the use of `$id`, `$anchor`, or any other mechanism,
1054+
implementations SHOULD raise an error condition. Otherwise the result is
1055+
undefined, and even if documented will not be interoperable.
10631056

10641057
#### Schema References {#references}
10651058

@@ -1093,12 +1086,10 @@ resolve. This is useful for cases such as authoring a recursive schema that can
10931086
be extended or a generic schema such as a list whose items are defined by the
10941087
referencing schema.
10951088

1096-
The value of the `$dynamicRef` property MUST be formatted as a valid
1097-
[fragment-only IRI](#fragments).[^8]
1089+
The value of the `$dynamicRef` property MUST be a string and MUST conform to the
1090+
plain name fragment identifier syntax defined in {{fragments}}.[^3]
10981091

1099-
[^8]: `$dynamicAnchor` defines the anchor with plain text, e.g. `foo`. Although,
1100-
for historical reasons, the value of `$dynamicRef` still uses a fragment-only
1101-
IRI syntax, e.g. `#foo`.
1092+
[^3]: `$dynamicAnchor` and `$dynamicRef` form a string-matched pair.
11021093

11031094
Resolution of `$dynamicRef` begins by identifying the outermost schema resource
11041095
in the [dynamic scope](#scopes) which defines a matching `$dynamicAnchor`. The
@@ -2322,7 +2313,7 @@ and only allows the "data" and "children" properties. An example instance with
23222313
"children": {
23232314
"type": "array",
23242315
"items": {
2325-
"$dynamicRef": "#node"
2316+
"$dynamicRef": "node"
23262317
}
23272318
}
23282319
}
@@ -2347,50 +2338,34 @@ and only allows the "data" and "children" properties. An example instance with
23472338
```
23482339

23492340
When we load these two schemas, we will notice the `$dynamicAnchor` named "node"
2350-
(note the lack of "#" as this is just the name) present in each, resulting in
2351-
the following full schema IRIs:
2352-
2353-
- `https://example.com/tree#node`
2354-
- `https://example.com/strict-tree#node`
2355-
2356-
In addition, JSON Schema implementations keep track of the fact that these
2357-
fragment identifiers were created with `$dynamicAnchor`.
2341+
present in each.
23582342

23592343
If we apply the "strict-tree" schema to the instance, we will follow the `$ref`
23602344
to the "tree" schema, examine its "children" subschema, and find the
2361-
`$dynamicRef`: to "#node" (note the `#` for IRI fragment syntax) in its `items`
2362-
subschema. That reference resolves to `https://example.com/tree#node`, which is
2363-
a IRI with a fragment created by `$dynamicAnchor`. Therefore we must examine the
2364-
dynamic scope before following the reference.
2345+
`$dynamicRef` to "node" in its `items` subschema. That reference resolves to
2346+
the `$dynamicAnchor` with value "node" in `https://example.com/tree`. Therefore
2347+
we must examine the dynamic scope before following the reference.
23652348

23662349
At this point, the evaluation path is
23672350
`/$ref/properties/children/items/$dynamicRef`, with a dynamic scope containing
23682351
(from the outermost scope to the innermost):
23692352

2370-
1. `https://example.com/strict-tree#`
2371-
1. `https://example.com/tree#`
2372-
1. `https://example.com/tree#/properties/children`
2373-
1. `https://example.com/tree#/properties/children/items`
2374-
2375-
Since we are looking for a plain name fragment identifier, which can be defined
2376-
anywhere within a schema resource, the JSON Pointer IRI fragments are irrelevant
2377-
to this check. That means that we can remove the fragments and eliminate
2378-
consecutive duplicates, producing:
2379-
23802353
1. `https://example.com/strict-tree`
2381-
1. `https://example.com/tree`
2354+
2. `https://example.com/tree`
23822355

2383-
In this case, the outermost resource also has a "node" fragment identifier
2384-
defined by `$dynamicAnchor`. Therefore instead of resolving the `$dynamicRef` to
2385-
`https://example.com/tree#node`, we resolve it to
2386-
`https://example.com/strict-tree#node`.
2356+
To find the resolution target of the `$dynamicRef`, we start at the outermost
2357+
dynamic scope and traverse inward, stopping when we find a schema resource that
2358+
defines a matching `$dynamicAnchor`.
23872359

2388-
The reference in the "tree" schema resolves to the root of "strict-tree", so
2389-
"strict-tree" is applied not only to the tree instance's root, but also its
2390-
children.
2360+
In this case, the outermost resource "strict-tree" has a "node" identifier
2361+
defined by `$dynamicAnchor`. The subschema that defines that anchor is the
2362+
resolution target of the `$dynamicRef`. Therefore instead of resolving the
2363+
`$dynamicRef` to the `"$dynamicAnchor": "node"` in `https://example.com/tree`,
2364+
we resolve it to the `"$dynamicAnchor": "node"` in
2365+
`https://example.com/strict-tree`.
23912366

23922367
This example shows both `$dynamicAnchor`s in the same place in each schema,
2393-
specifically the resource root schema. Since plain-name fragment identifiers are
2368+
specifically the resource root schema. Since plain-name identifiers are
23942369
independent of the JSON structure, this would work just as well if one or both
23952370
of the node schema objects were moved under `$defs`. It is the matching
23962371
`$dynamicAnchor` values which tell us how to resolve the dynamic reference, not

0 commit comments

Comments
 (0)