@@ -22,16 +22,13 @@ For this example, let's say we want to define a customer record, where
22
22
each customer may have both a shipping and a billing address.
23
23
Addresses are always the same---they have a street address, city and
24
24
state---so we don't want to duplicate that part of the schema
25
- everywhere we want to store an address. Not only does it make the
25
+ everywhere we want to store an address. Not only would that make the
26
26
schema more verbose, but it makes updating it in the future more
27
- difficult. If our imaginary company were to start international
27
+ difficult. If our imaginary company were to start doing international
28
28
business in the future and we wanted to add a country field to all the
29
29
addresses, it would be better to do this in a single place rather than
30
30
everywhere that addresses are used.
31
31
32
- .. note ::
33
- This is part of the draft 4 spec only, and does not exist in draft 3.
34
-
35
32
So let's start with the schema that defines an address::
36
33
37
34
{
@@ -72,17 +69,22 @@ refer to the above, we would include::
72
69
73
70
{ "$ref": "#/definitions/address" }
74
71
75
- The value of ``$ref `` is a string in a format called `JSON Pointer
72
+ This can be used anywhere a schema is expected. You will always use ``$ref `` as
73
+ the only key in an object: any other keys you put there will be ignored by the
74
+ validator.
75
+
76
+ The value of ``$ref `` is a URI, and the part after ``# `` sign (the
77
+ "fragment" or "named anchor") is in a format called `JSON Pointer
76
78
<https://tools.ietf.org/html/rfc6901> `__.
77
79
78
80
.. note ::
79
81
JSON Pointer aims to serve the same purpose as `XPath
80
82
<http://www.w3.org/TR/xpath/> `_ from the XML world, but it is much
81
83
simpler.
82
84
83
- The pound symbol (`` # ``) refers to the current document, and then the
84
- slash (``/ ``) separated keys thereafter just traverse the keys in the
85
- objects in the document. Therefore, in our example
85
+ If you're using a definition from the same document, the `` $ref `` value begins
86
+ with the pound symbol (``# ``). Following that, the slash-separated items traverse
87
+ the keys in the objects in the document. Therefore, in our example
86
88
``"#/definitions/address" `` means:
87
89
88
90
1) go to the root of the document
@@ -139,22 +141,108 @@ schema for a customer:
139
141
}
140
142
}
141
143
144
+ .. note ::
145
+
146
+ Even though the value of a ``$ref `` is a URI, it is not a network locator,
147
+ only an identifier. The schema may not actually exist at the address
148
+ specified. It is basically up to the validator implementation how external
149
+ schema URIs will be handled, but one should not assume the validator will
150
+ fetch network resources indicated in ``$ref `` values.
151
+
152
+ Recursion
153
+ `````````
154
+
155
+ ``$ref `` elements may be used to create recursive schemas that refer to themselves.
156
+ For example, you might have a ``person `` schema that has an array of ``children ``, each of which are also ``person `` instances.
157
+
158
+ .. schema_example ::
159
+
160
+ {
161
+ "$schema": "http://json-schema.org/draft-06/schema#",
162
+
163
+ "definitions": {
164
+ "person": {
165
+ "type": "object",
166
+ "properties": {
167
+ "name": { "type": "string" },
168
+ "children": {
169
+ "type": "array",
170
+ * "items": { "$ref": "#/definitions/person" },
171
+ "default": []
172
+ }
173
+ }
174
+ }
175
+ },
176
+
177
+ "type": "object",
178
+
179
+ "properties": {
180
+ "person": { "$ref": "#/definitions/person" }
181
+ }
182
+ }
183
+ --
184
+ // A snippet of the British royal family tree
185
+ {
186
+ "person": {
187
+ "name": "Elizabeth",
188
+ "children": [
189
+ {
190
+ "name": "Charles",
191
+ "children": [
192
+ {
193
+ "name": "William",
194
+ "children": [
195
+ { "name": "George" },
196
+ { "name": "Charlotte" }
197
+ ]
198
+ },
199
+ {
200
+ "name": "Harry"
201
+ }
202
+ ]
203
+ }
204
+ ]
205
+ }
206
+ }
207
+
208
+ However, a loop of ``$ref `` schemas referring to one another could cause
209
+ infinite recursion in the validator, and is explicitly disallowed.
210
+
211
+ .. schema_example ::
212
+
213
+ {
214
+ "definitions": {
215
+ "alice": {
216
+ "anyOf": [
217
+ { "$ref": "#/definitions/bob" }
218
+ ]
219
+ },
220
+ "bob": {
221
+ "anyOf": [
222
+ { "$ref": "#/definitions/alice" }
223
+ ]
224
+ }
225
+ }
226
+ }
227
+
228
+ .. index ::
229
+ single: $id
230
+
142
231
.. _id :
143
232
144
233
The $id property
145
234
----------------
146
235
147
- |draft6 |
148
-
149
- The ``$id `` property serves two purposes:
236
+ The ``$id `` property is a URI that serves two purposes:
150
237
151
238
- It declares a unique identifier for the schema.
152
239
153
- - It declares a base URL against which ``$ref `` URLs are resolved.
240
+ - It declares a base URI against which ``$ref `` URIs are resolved.
154
241
155
- It is best practice that ``$id `` is a URL, preferably in a domain that
156
- you control. For example, if you own the ``foo.bar `` domain, and you
157
- had a schema for addresses, you may set its ``$id `` as follows:
242
+ It is best practice that every top-level schema should set ``$id `` to an
243
+ absolute URI, with a domain that you control. For example, if you own the
244
+ ``foo.bar `` domain, and you had a schema for addresses, you may set its ``$id ``
245
+ as follows:
158
246
159
247
.. schema_example ::
160
248
@@ -171,25 +259,72 @@ For example, if you had:
171
259
172
260
{ "$ref": "person.json" }
173
261
174
- in the same file, a JSON schema validation library would fetch ``person.json ``
175
- from ``http://foo.bar/schemas/person.json ``, even if ``address.json `` was loaded
176
- from somewhere else, such as the local filesystem.
262
+ in the same file, a JSON schema validation library that supported network
263
+ fetching would fetch ``person.json `` from
264
+ ``http://foo.bar/schemas/person.json ``, even if ``address.json `` was loaded from
265
+ somewhere else, such as the local filesystem.
266
+
267
+ |draft6 |
177
268
178
269
.. draft_specific ::
179
270
180
271
--Draft 4
181
272
In Draft 4, ``$id `` is just ``id `` (without the dollar sign).
182
273
274
+ The ``$id `` property should never be the empty string or an empty fragment
275
+ (``# ``), since that doesn't really make sense.
276
+
277
+ Using $id with $ref
278
+ ```````````````````
279
+
280
+ ``$id `` also provides a way to refer to subschema without using JSON Pointer.
281
+ This means you can refer to them by a unique name, rather than by where they
282
+ appear in the JSON tree.
283
+
284
+ Reusing the address example above, we can add an ``$id `` property to the
285
+ address schema, and refer to it by that instead.
286
+
287
+ .. schema_example ::
288
+
289
+ {
290
+ "$schema": "http://json-schema.org/draft-06/schema#",
291
+
292
+ "definitions": {
293
+ "address": {
294
+ *"$id": "#address",
295
+ "type": "object",
296
+ "properties": {
297
+ "street_address": { "type": "string" },
298
+ "city": { "type": "string" },
299
+ "state": { "type": "string" }
300
+ },
301
+ "required": ["street_address", "city", "state"]
302
+ }
303
+ },
304
+
305
+ "type": "object",
306
+
307
+ "properties": {
308
+ *"billing_address": { "$ref": "#address" },
309
+ *"shipping_address": { "$ref": "#address" }
310
+ }
311
+ }
312
+
313
+ .. note ::
314
+
315
+ This functionality isn't currently supported by the Python ``jsonschema ``
316
+ library.
317
+
183
318
Extending
184
319
---------
185
320
186
- The power of ``$ref `` really shines when it is combined with the
321
+ The power of ``$ref `` really shines when it is used with the
187
322
combining keywords ``allOf ``, ``anyOf `` and ``oneOf `` (see
188
323
:ref: `combining `).
189
324
190
- Let's say that for shipping address, we want to know whether the
325
+ Let's say that for a shipping address, we want to know whether the
191
326
address is a residential or business address, because the shipping
192
- method used may depend on that. For the billing address, we don't
327
+ method used may depend on that. For a billing address, we don't
193
328
want to store that information, because it's not applicable.
194
329
195
330
To handle this, we'll update our definition of shipping address::
0 commit comments