|
315 | 315 | of five categories:
|
316 | 316 | <list style="hanging">
|
317 | 317 | <t hangText="identifiers:">
|
318 |
| - control schema identification through setting the schema's |
319 |
| - canonical URI and/or changing how the base URI is determined |
| 318 | + control schema identification through setting a URI |
| 319 | + for the schema and/or changing how the base URI is determined |
320 | 320 | </t>
|
321 | 321 | <t hangText="assertions:">
|
322 | 322 | produce a boolean result when applied to an instance
|
|
419 | 419 | <t>
|
420 | 420 | A JSON Schema resource is a schema which is
|
421 | 421 | <xref target="RFC6596">canonically</xref> identified by an
|
422 |
| - <xref target="RFC3986">absolute URI</xref>. |
| 422 | + <xref target="RFC3986">absolute URI</xref>. Schema resources MAY |
| 423 | + also be identified by URIs including fragments. Any such URIs |
| 424 | + are considered to be non-canonical. |
423 | 425 | </t>
|
424 | 426 | <t>
|
425 | 427 | The root schema is the schema that comprises the entire JSON document
|
|
723 | 725 | be able to support those keywords or vocabularies that contain them.
|
724 | 726 | </t>
|
725 | 727 | </section>
|
726 |
| - <section title="Identifiers" anchor="identifiers"> |
| 728 | + <section title="Identifiers"> |
727 | 729 | <t>
|
728 |
| - Identifiers set the canonical URI of a schema, or affect how such URIs are |
| 730 | + Identifiers define URIs for a schema, or affect how such URIs are |
729 | 731 | resolved in <xref target="references">references</xref>, or both.
|
730 | 732 | The Core vocabulary defined in this document defines several
|
731 | 733 | identifying keywords, most notably "$id".
|
|
1333 | 1335 | <t>
|
1334 | 1336 | If present, the value for this keyword MUST be a string, and MUST represent a
|
1335 | 1337 | valid <xref target="RFC3986">URI-reference</xref>. This URI-reference
|
1336 |
| - SHOULD be normalized, and MUST resolve to an |
1337 |
| - <xref target="RFC3986">absolute-URI</xref> (without a fragment). Therefore, |
1338 |
| - "$id" MUST NOT contain a non-empty fragment, and SHOULD NOT contain an |
1339 |
| - empty fragment. |
| 1338 | + SHOULD be normalized, and MUST be semantically equivalent to an |
| 1339 | + <xref target="RFC3986">absolute-URI</xref> (without a fragment). |
1340 | 1340 | </t>
|
1341 | 1341 | <t>
|
1342 |
| - Since an empty fragment in the context of the application/schema+json media |
1343 |
| - type refers to the same resource as the base URI without a fragment, |
1344 |
| - an implementation MAY normalize a URI ending with an empty fragment by removing |
1345 |
| - the fragment. However, schema authors SHOULD NOT rely on this behavior |
1346 |
| - across implementations. |
| 1342 | + The application/schema+json media type defines that an absolute-URI |
| 1343 | + identifying a resource and the same URI with an empty fragment |
| 1344 | + appended (which identifies the resource's root schema object) are |
| 1345 | + semantically equivalent. Since this semantic equivalence is not part |
| 1346 | + of the <xref target="RFC3986">RFC 3986 normalization process</xref>, |
| 1347 | + implementors and schema authors cannot rely on generic URI libraries |
| 1348 | + understanding the equivalence. |
| 1349 | + </t> |
| 1350 | + <t> |
| 1351 | + Therefore, "$id" MUST NOT contain a non-empty fragment, and SHOULD NOT |
| 1352 | + contain an empty fragment. The absolute-URI form MUST be considered |
| 1353 | + the canonical URI, regardless of the presence or absence of an empty fragment. |
1347 | 1354 | <cref>
|
1348 |
| - This is primarily allowed because older meta-schemas have an empty |
1349 |
| - fragment in their $id (or previously, id). A future draft may outright |
1350 |
| - forbid even empty fragments in "$id". |
| 1355 | + An empty fragment is currently allowed because older meta-schemas have |
| 1356 | + an empty fragment in their $id (or previously, id). |
| 1357 | + A future draft may outright forbid even empty fragments in "$id". |
1351 | 1358 | </cref>
|
1352 | 1359 | </t>
|
1353 | 1360 | <t>
|
1354 |
| - This URI also serves as the base URI for relative URI-references in keywords |
1355 |
| - within the schema resource, in accordance with |
| 1361 | + The absolute-URI also serves as the base URI for relative URI-references |
| 1362 | + in keywords within the schema resource, in accordance with |
1356 | 1363 | <xref target="RFC3986">RFC 3986 section 5.1.1</xref> regarding base URIs
|
1357 | 1364 | embedded in content.
|
1358 | 1365 | </t>
|
|
1616 | 1623 | media type.
|
1617 | 1624 | </t>
|
1618 | 1625 | <t>
|
1619 |
| - Unless the "$id" keyword described in the next section is present in the |
| 1626 | + Unless the "$id" keyword described in an earlier section is present in the |
1620 | 1627 | root schema, this base URI SHOULD be considered the canonical URI of the
|
1621 | 1628 | schema document's root schema resource.
|
1622 | 1629 | </t>
|
|
1743 | 1750 | Since JSON Pointer URI fragments are constructed based on the structure
|
1744 | 1751 | of the schema document, an embedded schema resource and its subschemas
|
1745 | 1752 | can be identified by JSON Pointer fragments relative to either its own
|
1746 |
| - canonical URI, or relative to the containing resource's URI. |
| 1753 | + canonical URI, or relative to a containing resource's URI. |
1747 | 1754 | </t>
|
1748 | 1755 | <t>
|
1749 | 1756 | Conceptually, a set of linked schema resources should behave
|
|
1775 | 1782 | }
|
1776 | 1783 | ]]>
|
1777 | 1784 | </artwork>
|
1778 |
| - <postamble> |
1779 |
| - The URI "https://example.com/foo#/items/additionalProperties" |
1780 |
| - points to the schema of the "additionalProperties" keyword in |
1781 |
| - the embedded resource. The canonical URI of that schema, however, |
1782 |
| - is "https://example.com/bar#/additionalProperties". |
1783 |
| - </postamble> |
1784 | 1785 | </figure>
|
| 1786 | + <t> |
| 1787 | + The URI "https://example.com/foo#/items" points to the "items" schema, |
| 1788 | + which is an embedded resource. The canonical URI of that schema |
| 1789 | + resource, however, is "https://example.com/bar". |
| 1790 | + </t> |
| 1791 | + <t> |
| 1792 | + For the "additionalProperties" schema within that embedded resource, |
| 1793 | + the URI "https://example.com/foo#/items/additionalProperties" points |
| 1794 | + to the correct object, but that object's URI relative to its resource's |
| 1795 | + canonical URI is "https://example.com/bar#/additionalProperties". |
| 1796 | + </t> |
1785 | 1797 | <figure>
|
1786 | 1798 | <preamble>
|
1787 | 1799 | Now consider the following two schema resources linked by reference
|
|
1803 | 1815 | ]]>
|
1804 | 1816 | </artwork>
|
1805 | 1817 | <postamble>
|
1806 |
| - Here we see that the canonical URI for that "additionalProperties" |
1807 |
| - subschema is still valid, while the non-canonical URI with the fragment |
1808 |
| - beginning with "#/items/$ref" now resolves to nothing. |
| 1818 | + Here we see that the URI for the "additionalProperties" schema object |
| 1819 | + that is relative to its resource's canonical URI is still valid, |
| 1820 | + while the URI relative to the "items" schema object's URI no longer |
| 1821 | + resolves to anything. |
1809 | 1822 | </postamble>
|
1810 | 1823 | </figure>
|
1811 | 1824 | <t>
|
1812 | 1825 | Note also that "https://example.com/foo#/items" is valid in both
|
1813 | 1826 | arrangements, but resolves to a different value. This URI ends up
|
1814 |
| - functioning similarly to a retrieval URI for a resource. While valid, |
1815 |
| - examining the resolved value and either using the "$id" (if the value |
1816 |
| - is a subschema), or resolving the reference and using the "$id" of the |
1817 |
| - reference target, is preferable. |
| 1827 | + functioning similarly to a retrieval URI for a resource. While this URI |
| 1828 | + is valid, it is more robust to use the "$id" of the embedded or referenced |
| 1829 | + resource unless it is specifically desired to identify the object containing |
| 1830 | + the "$ref" in the second (non-embedded) arrangement. |
1818 | 1831 | </t>
|
1819 | 1832 | <t>
|
1820 |
| - An implementation MAY choose not to support addressing schemas |
1821 |
| - by non-canonical URIs. As such, it is RECOMMENDED that schema authors only |
1822 |
| - use canonical URIs, as using non-canonical URIs may reduce |
1823 |
| - schema interoperability. |
| 1833 | + An implementation MAY choose not to support addressing schema resource |
| 1834 | + contents by URIs using a base other than the resource's canonical URI, |
| 1835 | + plus a JSON Pointer fragment relative to that base. Therefore, schema |
| 1836 | + authors SHOULD NOT rely on such URIs, as using them may reduce interoperability. |
1824 | 1837 | <cref>
|
1825 | 1838 | This is to avoid requiring implementations to keep track of a whole
|
1826 | 1839 | stack of possible base URIs and JSON Pointer fragments for each,
|
|
1832 | 1845 | </cref>
|
1833 | 1846 | </t>
|
1834 | 1847 | <t>
|
1835 |
| - Further examples of such non-canonical URIs, as well as the appropriate |
1836 |
| - canonical URIs to use instead, are provided in appendix |
1837 |
| - <xref target="idExamples" format="counter"></xref>. |
| 1848 | + Further examples of such non-canonical URI construction, as well as |
| 1849 | + the appropriate canonical URI-based fragments to use instead, |
| 1850 | + are provided in appendix <xref target="idExamples" format="counter"></xref>. |
1838 | 1851 | </t>
|
1839 | 1852 | </section>
|
1840 | 1853 | </section>
|
|
2695 | 2708 | <section title="Keyword Absolute Location">
|
2696 | 2709 | <t>
|
2697 | 2710 | The absolute, dereferenced location of the validating keyword. The value MUST
|
2698 |
| - be expressed as a full URI using the canonical URI of the relevant |
2699 |
| - schema object, and it MUST NOT include by-reference applicators |
| 2711 | + be expressed as a full URI using the canonical URI of the relevant schema resource |
| 2712 | + with a JSON Pointer fragment, and it MUST NOT include by-reference applicators |
2700 | 2713 | such as "$ref" or "$dynamicRef" as non-terminal path components.
|
2701 | 2714 | It MAY end in such keywords if the error or annotation is for that
|
2702 | 2715 | keyword, such as an unresolvable reference.
|
@@ -3332,76 +3345,76 @@ https://example.com/schemas/common#/$defs/count/minimum
|
3332 | 3345 | <list style="hanging">
|
3333 | 3346 | <t hangText="# (document root)">
|
3334 | 3347 | <list style="hanging">
|
3335 |
| - <t hangText="canonical absolute-URI (and also base URI)"> |
| 3348 | + <t hangText="canonical (and base) URI"> |
3336 | 3349 | https://example.com/root.json
|
3337 | 3350 | </t>
|
3338 |
| - <t hangText="canonical URI with pointer fragment"> |
| 3351 | + <t hangText="canonical resource URI plus pointer fragment"> |
3339 | 3352 | https://example.com/root.json#
|
3340 | 3353 | </t>
|
3341 | 3354 | </list>
|
3342 | 3355 | </t>
|
3343 | 3356 | <t hangText="#/$defs/A">
|
3344 | 3357 | <list>
|
3345 | 3358 | <t hangText="base URI">https://example.com/root.json</t>
|
3346 |
| - <t hangText="canonical URI with plain fragment"> |
| 3359 | + <t hangText="canonical resource URI plus plain fragment"> |
3347 | 3360 | https://example.com/root.json#foo
|
3348 | 3361 | </t>
|
3349 |
| - <t hangText="canonical URI with pointer fragment"> |
| 3362 | + <t hangText="canonical resource URI plus pointer fragment"> |
3350 | 3363 | https://example.com/root.json#/$defs/A
|
3351 | 3364 | </t>
|
3352 | 3365 | </list>
|
3353 | 3366 | </t>
|
3354 | 3367 | <t hangText="#/$defs/B">
|
3355 | 3368 | <list style="hanging">
|
3356 |
| - <t hangText="base URI">https://example.com/other.json</t> |
3357 |
| - <t hangText="canonical URI with pointer fragment"> |
| 3369 | + <t hangText="canonical (and base) URI">https://example.com/other.json</t> |
| 3370 | + <t hangText="canonical resource URI plus pointer fragment"> |
3358 | 3371 | https://example.com/other.json#
|
3359 | 3372 | </t>
|
3360 |
| - <t hangText="non-canonical URI with fragment relative to root.json"> |
| 3373 | + <t hangText="base URI of enclosing (root.json) resource plus fragment"> |
3361 | 3374 | https://example.com/root.json#/$defs/B
|
3362 | 3375 | </t>
|
3363 | 3376 | </list>
|
3364 | 3377 | </t>
|
3365 | 3378 | <t hangText="#/$defs/B/$defs/X">
|
3366 | 3379 | <list style="hanging">
|
3367 | 3380 | <t hangText="base URI">https://example.com/other.json</t>
|
3368 |
| - <t hangText="canonical URI with plain fragment"> |
| 3381 | + <t hangText="canonical resource URI plus plain fragment"> |
3369 | 3382 | https://example.com/other.json#bar
|
3370 | 3383 | </t>
|
3371 |
| - <t hangText="canonical URI with pointer fragment"> |
| 3384 | + <t hangText="canonical resource URI plus pointer fragment"> |
3372 | 3385 | https://example.com/other.json#/$defs/X
|
3373 | 3386 | </t>
|
3374 |
| - <t hangText="non-canonical URI with fragment relative to root.json"> |
| 3387 | + <t hangText="base URI of enclosing (root.json) resource plus fragment"> |
3375 | 3388 | https://example.com/root.json#/$defs/B/$defs/X
|
3376 | 3389 | </t>
|
3377 | 3390 | </list>
|
3378 | 3391 | </t>
|
3379 | 3392 | <t hangText="#/$defs/B/$defs/Y">
|
3380 | 3393 | <list style="hanging">
|
3381 |
| - <t hangText="base URI">https://example.com/t/inner.json</t> |
3382 |
| - <t hangText="canonical URI with plain fragment"> |
| 3394 | + <t hangText="canonical (and base) URI">https://example.com/t/inner.json</t> |
| 3395 | + <t hangText="canonical URI plus plain fragment"> |
3383 | 3396 | https://example.com/t/inner.json#bar
|
3384 | 3397 | </t>
|
3385 |
| - <t hangText="canonical URI with pointer fragment"> |
| 3398 | + <t hangText="canonical URI plus pointer fragment"> |
3386 | 3399 | https://example.com/t/inner.json#
|
3387 | 3400 | </t>
|
3388 |
| - <t hangText="non-canonical URI with fragment relative to other.json"> |
| 3401 | + <t hangText="base URI of enclosing (other.json) resource plus fragment"> |
3389 | 3402 | https://example.com/other.json#/$defs/Y
|
3390 | 3403 | </t>
|
3391 |
| - <t hangText="non-canonical URI with fragment relative to root.json"> |
| 3404 | + <t hangText="base URI of enclosing (root.json) resource plus fragment"> |
3392 | 3405 | https://example.com/root.json#/$defs/B/$defs/Y
|
3393 | 3406 | </t>
|
3394 | 3407 | </list>
|
3395 | 3408 | </t>
|
3396 | 3409 | <t hangText="#/$defs/C">
|
3397 | 3410 | <list style="hanging">
|
3398 |
| - <t hangText="base URI"> |
| 3411 | + <t hangText="canonical (and base) URI"> |
3399 | 3412 | urn:uuid:ee564b8a-7a87-4125-8c96-e9f123d6766f
|
3400 | 3413 | </t>
|
3401 |
| - <t hangText="canonical URI with pointer fragment"> |
| 3414 | + <t hangText="canonical URI plus pointer fragment"> |
3402 | 3415 | urn:uuid:ee564b8a-7a87-4125-8c96-e9f123d6766f#
|
3403 | 3416 | </t>
|
3404 |
| - <t hangText="non-canonical URI with fragment relative to root.json"> |
| 3417 | + <t hangText="base URI of enclosing (root.json) resource plus fragment"> |
3405 | 3418 | https://example.com/root.json#/$defs/C
|
3406 | 3419 | </t>
|
3407 | 3420 | </list>
|
@@ -3433,16 +3446,16 @@ https://example.com/schemas/common#/$defs/count/minimum
|
3433 | 3446 | <t>
|
3434 | 3447 | This transformation can be safely and reversibly done as long as
|
3435 | 3448 | all static references (e.g. "$ref") use URI-references that resolve
|
3436 |
| - to canonical URIs, and all schema resources have an absolute-URI |
3437 |
| - as the "$id" in their root schema. |
| 3449 | + to URIs using the canonical resource URI as the base, and all schema |
| 3450 | + resources have an absolute-URI as the "$id" in their root schema. |
3438 | 3451 | </t>
|
3439 | 3452 | <t>
|
3440 | 3453 | With these conditions met, each external resource can be copied
|
3441 | 3454 | under "$defs", without breaking any references among the resources'
|
3442 | 3455 | schema objects, and without changing any aspect of validation or
|
3443 | 3456 | annotation results. The names of the schemas under "$defs" do
|
3444 | 3457 | not affect behavior, assuming they are each unique, as they
|
3445 |
| - do not appear in canonical URIs for the embedded resources. |
| 3458 | + do not appear in the canonical URIs for the embedded resources. |
3446 | 3459 | </t>
|
3447 | 3460 | </section>
|
3448 | 3461 | <section title="Reference removal is not always safe">
|
|
0 commit comments