@@ -20,3 +20,210 @@ related:
2020 - vocabulary : validation
2121 keyword : definitions
2222---
23+
24+ The [ ` $ref ` ] ({{< ref "draft4/core/ref" >}}) keyword enables a schema to
25+ reference another schema by its URI, effectively importing its keywords into the
26+ current evaluation process. This keyword is the cornerstone of schema
27+ composition, allowing complex schemas to be created out of simpler ones. A
28+ reference may set its URI fragment to a [ JSON
29+ Pointer] ( https://www.rfc-editor.org/rfc/rfc6901 ) that determines the destination
30+ of the reference after first resolving the rest of the URI.
31+
32+ {{<common-pitfall >}}
33+
34+ In JSON Schema [ Draft 7] ( /draft7 ) and earlier versions, ** any subschema
35+ declaring the [ ` $ref ` ] ({{< ref "draft4/core/ref" >}}) keyword is considered to
36+ be a _ reference object_ and any other sibling keyword is silently ignored** . As
37+ a consequence, subschemas with references that make use of other keywords must
38+ artificially wrap the reference into its own subschema using keywords like
39+ [ ` allOf ` ] ({{< ref "draft4/validation/allof" >}}).
40+
41+ {{</common-pitfall >}}
42+
43+ {{<common-pitfall >}}
44+
45+ ** Avoid referencing other schema files using their file paths** . While some
46+ implementations support this by automatically constructing schema URIs that
47+ make use of the ` file:// ` scheme, this is not enforced behaviour. The only
48+ standard and guaranteed mechanism of declaring a schema URI for identification
49+ and referencing purposes is through the [ ` id ` ] ({{< ref "draft4/core/id" >}}) keyword.
50+
51+ {{</common-pitfall >}}
52+
53+ {{<common-pitfall >}}
54+
55+ The target of a reference must be a schema. Referencing a JSON value that is
56+ not unambiguously recognised as a schema leads to undefined behaviour. This
57+ not only includes referencing arbitrary JSON files (the obvious case), but
58+ also referencing parts of a schema that a JSON Schema evaluator does not
59+ consider to be a subschema.
60+
61+ {{</common-pitfall >}}
62+
63+ References are either _ internal_ (pointing at schemas within the same schema
64+ definition) or _ external_ (pointing at schema resources outside the given schema
65+ definition). If the reference is a relative URI, it is resolved against the
66+ _ current_ base URI, which is either the closest parent URI as set by the
67+ [ ` id ` ] ({{< ref "draft4/core/id" >}}) keyword, or the base URI as determined by
68+ the context on which the schema is declared. Schema wrappers like OpenAPI are
69+ notable examples of the latter. A relative reference from a schema embedded in
70+ an OpenAPI specification is resolved from the root of the API specification, and
71+ not from the root of the schema.
72+
73+ {{<best-practice >}}
74+
75+ It is highly recommended to make use of _ external_ references to break down
76+ complex monolithic schemas into smaller schema files. However, for performance
77+ and integrity reasons, avoid resolving these external schemas (i.e. over HTTP
78+ or the filesystem) at runtime.
79+
80+ You can automatically inline external references at build time using the
81+ [ `jsonschema
82+ bundle`] ( https://github.com/sourcemeta/jsonschema/blob/main/docs/bundle.markdown )
83+ command.
84+
85+ {{</best-practice >}}
86+
87+ Note that a reference to an absolute URI does not necessarily mean that the
88+ reference is external. Conversely, a reference to a relative URI does not
89+ necessarily mean that the reference is internal. When encountering any type
90+ of reference, a JSON Schema implementation will check if the root schema
91+ resource or its nested schema resources (if any) declare the canonically
92+ resolved version of such URI through the [ ` id ` ] ({{< ref "draft4/core/id"
93+ > }}) keyword. If so, the reference is considered internal. This
94+ internal-first lookup is what enables the standard
95+ [ bundling] ( https://json-schema.org/blog/posts/bundling-json-schema-compound-documents )
96+ process.
97+
98+ {{<learning-more >}}
99+
100+ If you are having a hard time understanding references and some of its more
101+ subtle scenarios (like base URI resolution), it is probably because you don't
102+ have a strong grasp of URIs yet (a notably hard but universal
103+ pre-requisite!).
104+
105+ To learn more about URIs, we strongly suggest studying the [ IETF RFC
106+ 3986] ( https://www.rfc-editor.org/info/rfc3986 ) URI standard. To avoid
107+ confusion, note that there is also a [ WHATWG URL
108+ Standard] ( https://url.spec.whatwg.org ) that targets URLs in the context of
109+ web browsers. However, JSON Schema only implements and expects the IETF
110+ original standard. As a notable extension, this keyword supports referencing
111+ specific parts of a schema through the use of a JSON Pointer, so we also
112+ recommend studying the [ IETF RFC 6901] ( https://www.rfc-editor.org/info/rfc6901 )
113+ JSON Pointer standard and its [ URI fragment identifier
114+ representation] ( https://www.rfc-editor.org/rfc/rfc6901#section-6 ) .
115+
116+ {{</learning-more >}}
117+
118+ To debug references and how JSON Schema is interpreting your relative URIs,
119+ try the [ `jsonschema
120+ inspect`] ( https://github.com/sourcemeta/jsonschema/blob/main/docs/inspect.markdown )
121+ command. This command prints detailed information about each schema reference
122+ and of each location of the schema. For example:
123+
124+ ``` sh
125+ $ jsonschema inspect schema.json
126+ ...
127+
128+ (REFERENCE) ORIGIN: /properties/foo/$ref
129+ Type : Static
130+ Destination : https://example.com/schemas/example#/definitions/uuid
131+ - (w/o fragment) : https://example.com/schemas/example
132+ - (fragment) : /definitions/uuid
133+
134+ ...
135+ ```
136+
137+ ## Examples
138+
139+ {{<schema ` A schema whose keywords are mostly ignored given a non-wrapped sibling reference ` >}}
140+ {
141+ "$schema": "http://json-schema.org/draft-04/schema# ",
142+ "properties": {
143+ "foo": {
144+ "type": "string",
145+ "$ref": "#/definitions/test"
146+ }
147+ },
148+ "definitions": {
149+ "test": { "minLength": 2 }
150+ }
151+ }
152+ {{</schema >}}
153+
154+ {{<instance-pass ` A non-string value is valid as the reference overrides the type declaration ` >}}
155+ 12345
156+ {{</instance-pass >}}
157+
158+ {{<instance-pass ` A string value with a length equal or higher than 2 is valid ` >}}
159+ "foo"
160+ {{</instance-pass >}}
161+
162+ {{<instance-fail ` A string value with a length less than 2 is invalid ` >}}
163+ "x"
164+ {{</instance-fail >}}
165+
166+ {{<schema ` A schema that internally references the exact same helper schema in multiple equivalent ways ` >}}
167+ {
168+ "$schema": "http://json-schema.org/draft-04/schema# ",
169+ "id": "https://example.com/my-schema ",
170+ "properties": {
171+ "byRelativeFragmentPointer": {
172+ "$ref": "#/definitions/helper"
173+ },
174+ "byAbsoluteFragmentPointer": {
175+ "$ref": "https://example.com/my-schema#/definitions/helper "
176+ },
177+ "byRelativeURI": {
178+ "$ref": "my-helper"
179+ },
180+ "byRelativeRootPathURI": {
181+ "$ref": "/my-helper"
182+ },
183+ "byRelativeBackslashURI": {
184+ "$ref": "my-schema/../my-helper"
185+ },
186+ "byAbsoluteURI": {
187+ "$ref": "https://example.com/my-helper "
188+ }
189+ },
190+ "definitions": {
191+ "helper": {
192+ "id": "my-helper",
193+ "type": "string"
194+ }
195+ }
196+ }
197+ {{</schema >}}
198+
199+ {{<schema ` A schema that externally references the exact same schema URL in multiple equivalent ways ` >}}
200+ {
201+ "$schema": "http://json-schema.org/draft-04/schema# ",
202+ "id": "https://example.com/my-schema ",
203+ "properties": {
204+ "byAbsoluteURI": {
205+ "$ref": "https://example.com/my-other-schema "
206+ },
207+ "byRelativeURI": {
208+ "$ref": "my-other-schema"
209+ },
210+ "byRelativeRootPathURI": {
211+ "$ref": "/my-other-schema"
212+ },
213+ "byRelativeBackslashURI": {
214+ "$ref": "my-schema/../my-other-schema"
215+ }
216+ }
217+ }
218+ {{</schema >}}
219+
220+ {{<schema ` A schema that externally references a schema URN in the only possible way (URNs are always absolute) ` >}}
221+ {
222+ "$schema": "http://json-schema.org/draft-04/schema# ",
223+ "properties": {
224+ "byAbsoluteURI": {
225+ "$ref": "urn:example: my-other-schema "
226+ }
227+ }
228+ }
229+ {{</schema >}}
0 commit comments