@@ -1010,32 +1010,21 @@ fragments to identify subschemas is sometimes preferable because it is not tied
10101010to a particular structural location. This allows a subschema to be relocated
10111011without requiring references to be updated.
10121012
1013- The ` $anchor ` and ` $dynamicAnchor ` keywords are used to define
1014- location-independent identifiers for subschemas within a schema resource.
1015-
1016- ` $anchor ` defines a plain name fragment identifier that can be used in IRI
1017- fragments as an alternative to JSON Pointers.[ ^ 6 ] See {{fragments}}.
1013+ The ` $anchor ` keyword is used to define location-independent identifiers for
1014+ subschemas within a schema resource. ` $anchor ` defines a plain name fragment
1015+ identifier that can be used in IRI fragments as an alternative to JSON
1016+ Pointers.[ ^ 4 ] See {{fragments}}.
10181017
10191018[ ^ 6 ] : Note that the anchor string does not include the "#" character, as it is
10201019just a fragment identifier not an IRI reference. To reference the "foo"
10211020` $anchor ` from the same schema resource, you would use the fragment-only IRI
10221021` #foo ` . See below for full examples.
10231022
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.
1033-
1034- If present, the value of these keywords MUST be a string and MUST conform to the
1023+ If present, the value of this keyword MUST be a string and MUST conform to the
10351024plain name fragment identifier syntax defined in {{fragments}}.
10361025
1037- ` $anchor ` , ` $dynamicAnchor ` , and any extensions that define a plain name
1038- fragment identifiers MUST match XML's [ ` NCName `
1026+ ` $anchor ` , and any extensions that define a plain name fragment identifier MUST
1027+ match XML's [ ` NCName `
10391028production] ( https://www.w3.org/TR/2006/REC-xml-names11-20060816/#NT-NCName ) . For
10401029convenience, the ` NCName ` syntax is reproduced here in ABNF form, using a
10411030minimal set of rules:
@@ -1053,13 +1042,25 @@ NCNameChar = NCNameStartChar / "-" / "." / DIGIT
10531042 / %xB7 / %x0300-036F / %x203F-2040
10541043```
10551044
1045+ #### Defining dynamically scoped identifiers {#dynamic-anchors}
1046+
1047+ The ` $dynamicAnchor ` keyword is used to define location-independent identifiers
1048+ for subschemas within the dynamic scope of a schema evaluation. They are only
1049+ used by ` $dynamicRef ` . They are not meaningful in IRI fragments.
1050+
1051+ The fragment identifiers defined by ` $dynamicAnchor ` are not normal fragment
1052+ identifiers because they identify both the primary resource and the secondary
1053+ resource. See {{dynamic-ref}} for details.
1054+
1055+ If present, the value of this keyword MUST be a string.
1056+
10561057#### Duplicate schema identifiers {#duplicate-iris}
10571058
10581059A schema MAY (and likely will) have multiple IRIs, but there is no way for an
10591060IRI 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.
1061+ as the same IRI through the use of ` $id ` , ` $anchor ` , or any other mechanism,
1062+ implementations SHOULD raise an error condition. Otherwise the result is
1063+ undefined, and even if documented will not be interoperable.
10631064
10641065#### Schema References {#references}
10651066
@@ -1093,17 +1094,20 @@ resolve. This is useful for cases such as authoring a recursive schema that can
10931094be extended or a generic schema such as a list whose items are defined by the
10941095referencing schema.
10951096
1096- The value of the ` $dynamicRef ` property MUST be formatted as a valid
1097- [ fragment-only IRI ] ( # fragments) .[ ^ 8 ]
1097+ The value of the ` $dynamicRef ` property MUST be a string and MUST conform to the
1098+ plain name fragment identifier syntax defined in {{ fragments}} .[ ^ 3 ]
10981099
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 ` .
1100+ [ ^ 3 ] : The reason for limiting ` $dynamicAnchor ` to fragment identifier syntax no
1101+ longer exists because it isn't used in URIs, but the restriction remains to
1102+ avoid changing things that don't have a compelling reason to change.
1103+
1104+ ` $dynamicAnchor ` and ` $dynamicRef ` form a string-matched pair.
11021105
11031106Resolution of ` $dynamicRef ` begins by identifying the outermost schema resource
11041107in the [ dynamic scope] ( #scopes ) which defines a matching ` $dynamicAnchor ` . The
1105- schema to apply is the subschema of this resource which contains the matching
1106- ` $dynamicAnchor ` . If no matching ` $dynamicAnchor ` is found, see {{failed-refs}}.
1108+ schema to apply is the subschema of this resource which contains a
1109+ ` $dynamicAnchor ` matching the value of ` $dynamicRef ` . If no matching
1110+ ` $dynamicAnchor ` is found, see {{failed-refs}}.
11071111
11081112For a full example using these keywords, see {{dynamic-example}}.[ ^ 9 ]
11091113
@@ -2322,7 +2326,7 @@ and only allows the "data" and "children" properties. An example instance with
23222326 "children": {
23232327 "type": "array",
23242328 "items": {
2325- "$dynamicRef": "# node"
2329+ "$dynamicRef": "node"
23262330 }
23272331 }
23282332 }
@@ -2347,50 +2351,34 @@ and only allows the "data" and "children" properties. An example instance with
23472351```
23482352
23492353When 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 ` .
2354+ present in each.
23582355
23592356If we apply the "strict-tree" schema to the instance, we will follow the ` $ref `
23602357to 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.
2358+ ` $dynamicRef ` to "node" in its ` items ` subschema. That reference resolves to
2359+ the ` $dynamicAnchor ` with value "node" in ` https://example.com/tree ` . Therefore
2360+ we must examine the dynamic scope before following the reference.
23652361
23662362At this point, the evaluation path is
23672363` /$ref/properties/children/items/$dynamicRef ` , with a dynamic scope containing
23682364(from the outermost scope to the innermost):
23692365
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-
238023661 . ` https://example.com/strict-tree `
2381- 1 . ` https://example.com/tree `
2367+ 2 . ` https://example.com/tree `
23822368
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 ` .
2369+ To find the resolution target of the ` $dynamicRef ` , we start at the outermost
2370+ dynamic scope and traverse inward, stopping when we find a schema resource that
2371+ defines a matching ` $dynamicAnchor ` .
23872372
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.
2373+ In this case, the outermost resource "strict-tree" has a "node" identifier
2374+ defined by ` $dynamicAnchor ` . The subschema that defines that anchor is the
2375+ resolution target of the ` $dynamicRef ` . Therefore instead of resolving the
2376+ ` $dynamicRef ` to the ` "$dynamicAnchor": "node" ` in ` https://example.com/tree ` ,
2377+ we resolve it to the ` "$dynamicAnchor": "node" ` in
2378+ ` https://example.com/strict-tree ` .
23912379
23922380This example shows both ` $dynamicAnchor ` s in the same place in each schema,
2393- specifically the resource root schema. Since plain-name fragment identifiers are
2381+ specifically the resource root schema. Since dynamically scoped identifiers are
23942382independent of the JSON structure, this would work just as well if one or both
23952383of the node schema objects were moved under ` $defs ` . It is the matching
23962384` $dynamicAnchor ` values which tell us how to resolve the dynamic reference, not
0 commit comments