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