$dynamicAnchor : String
$dynamicAnchor
StringThis keyword is used to create plain name fragments that are not tied to any particular structural location for referencing purposes, which are taken into consideration for dynamic referencing.
Value |
This keyword must be set to a string starting with a letter and containing letters, digits, hyphens, underscores, colons, or periods
Hint: Use the jsonschema metaschema and jsonschema lint commands to catch keywords set to invalid values
|
---|---|
Kind | Identifier |
Applies To | Any |
Base Dialect | 2020-12 |
Changed In | None |
Introduced In | 2020-12 |
Vocabulary | Core |
Specification | https://json-schema.org/draft/2020-12/json-schema-core.html#section-8.2.2 |
Metaschema | https://json-schema.org/draft/2020-12/meta/core |
Official Tests | draft2020-12/dynamicRef.json |
Default | None |
Annotation | None |
Affected By | None |
Affects |
|
Also See |
The $dynamicAnchor
keyword is an
extension of the $anchor
keyword that
not only associates a subschema with the given URI fragment identifier, but
also records this association in the dynamic
scope. When
resolving a dynamic anchor using the $dynamicRef
keyword, the base URI of the origin is not
considered. Instead, evaluation jumps to the first encountered occurence of the
given dynamic anchor in the stack of schema
resources
traversed so far.
In other words, think of a schema declaring a dynamic anchor as offering an
overridable extension hook. For example, a schema that declares a dynamic
anchor foo
says: “I allow any parent schema to re-define this foo
subschema as they desire”, while keeping the rest of the schema intact.
Best Practice
Use dynamic references when you need to define generic and extensible schemas. In fact, the dynamic referencing mechanism is a direct translation of generic programming facilities like C++ template parameters and Java generics to JSON Schema. See the blog post Using Dynamic References to Support Generic Types by Greg Dennis (co-author of the JSON Schema specification) for a hands-on discussion of this concept.
Digging Deeper
The official JSON Schema meta-schemas define, by convention, a dynamic anchor
called meta
. This is a fundamental building block for schema extensibility.
The meta-schema of every vocabulary (official or third-party) hooks into this
dynamic anchor to extend the recursive definition of what constitutes a valid
schema for the given dialect.
More specifically, by relying on the meta
dynamic anchor, a vocabulary
meta-schema can validate the presence of a new keyword and have those
constraints be automatically discovered and applied by any applicator of any
other vocabulary (even future ones).
Common Pitfall
The schema resource from where the dynamic anchor lookup originates must declare such dynamic anchor. Otherwise, the schema would be unusable until another schema provides a definition for dynamic such anchor. This rule is informally referred to as the bookending requirement.
To debug which dynamic anchor the evaluation process is jumping to, try the
jsonschema validate
command with the --trace
option. This option prints a trace of every step in
the evaluation process alongside the corresponding keywords and their
respective locations, letting you know which destination was preferred when
encountering a dynamic reference. For example:
$ jsonschema validate string-list.json instance.json --resolve generic-list.json --trace
...
-> (push) "/$ref/items/$dynamicRef" (ControlDynamicAnchorJump)
at "/0"
at keyword location "https://example.com/generic-list#/items/$dynamicRef"
at vocabulary "https://json-schema.org/draft/2020-12/vocab/core"
-> (push) "/$ref/items/$dynamicRef/type" (AssertionTypeStrict)
at "/0"
at keyword location "https://example.com/string-list#/$defs/generic-list-item/type"
at vocabulary "https://json-schema.org/draft/2020-12/vocab/validation"
...
Examples
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/generic-list",
"type": "array",
"items": {
"$dynamicRef": "#generic-list-item"
},
"$defs": {
"default": {
"$comment": "This is a default declaration to satisfy the bookending requirement",
"$dynamicAnchor": "generic-list-item"
}
}
}
[]
[ 1, "foo", false ]
{ "keyword": "/items", "instance": "", "value": true }
"Hello World"
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/string-list",
"$ref": "https://example.com/generic-list",
"$defs": {
"generic-list-item": {
"$dynamicAnchor": "generic-list-item",
"type": "string"
}
}
}
[]
[ 1, "foo", false ]
[ "foo", "bar", "baz" ]
{ "keyword": "/$ref/items", "instance": "", "value": true }
"Hello World"