|
205 | 205 | The schemas to be applied may be present as subschemas comprising all or
|
206 | 206 | part of the keyword's value. Alternatively, an applicator may refer to
|
207 | 207 | a schema elsewhere in the same schema document, or in a different one.
|
208 |
| - The mechanism for identifying such referred schemas is defined by the |
| 208 | + The mechanism for identifying such referenced schemas is defined by the |
209 | 209 | keyword.
|
210 | 210 | </t>
|
211 | 211 | <t>
|
212 |
| - Applicator keywords also define how subschema or referred schema |
| 212 | + Applicator keywords also define how subschema or referenced schema |
213 | 213 | boolean <xref target="assertions">assertion</xref>
|
214 | 214 | results are modified and/or combined to produce the boolean result
|
215 | 215 | of the applicator. Applicators may apply any boolean logic operation
|
|
570 | 570 | As with the root schema, a subschema is either an object or a boolean.
|
571 | 571 | </t>
|
572 | 572 | </section>
|
573 |
| - <section title="Referred and Referring Schemas" anchor="referred"> |
| 573 | + <section title="Referenced and Referencing Schemas" anchor="referenced"> |
574 | 574 | <t>
|
575 | 575 | As noted in <xref target="applicators" />, an applicator keyword may
|
576 | 576 | refer to a schema to be applied, rather than including it as a
|
577 | 577 | subschema in the applicator's value. In such situations, the
|
578 |
| - schema being applied is known as the referred schema, while |
579 |
| - the schema containing the applicator keyword is the referring schema. |
| 578 | + schema being applied is known as the referenced schema, while |
| 579 | + the schema containing the applicator keyword is the referencing schema. |
580 | 580 | </t>
|
581 | 581 | <t>
|
582 | 582 | While root schemas and subschemas are static concepts based on a
|
583 |
| - schema's position within a schema document, referred and referring |
| 583 | + schema's position within a schema document, referenced and referencing |
584 | 584 | schemas are dynamic. Different pairs of schemas may find themselves
|
585 |
| - in various referred and referring arrangements during the evaluation |
| 585 | + in various referenced and referencing arrangements during the evaluation |
586 | 586 | of an instance against a schema.
|
587 | 587 | </t>
|
588 | 588 | <t>
|
589 | 589 | For some by-reference applicators, such as
|
590 |
| - <xref target="ref">"$ref"</xref>, the referred schema can be determined |
| 590 | + <xref target="ref">"$ref"</xref>, the referenced schema can be determined |
591 | 591 | by static analysis of the schema document. Others may take evaluation
|
592 | 592 | context into account, and only be resolvable in the process of evaluating
|
593 | 593 | with an instance.
|
|
740 | 740 | allow tools to follow the correct behaviour.
|
741 | 741 | </t>
|
742 | 742 | <t>
|
743 |
| - Note that the recursive nature of meta-schemas requires re-defining |
744 |
| - recursive keywords in the extended meta-schema, as can be seen in |
| 743 | + The "$recursiveRef" and "$recursiveAnchor" keywords exists to make |
| 744 | + extending recursive schemas such as meta-schemas easier, as can be seen in |
745 | 745 | the JSON Hyper-Schema meta-schema.
|
746 | 746 | </t>
|
747 | 747 | </section>
|
|
957 | 957 | <t>
|
958 | 958 | Several keywords can be used to reference a schema which is to be applied to the
|
959 | 959 | current instance location. "$ref" and "$recursiveRef" are an applicator
|
960 |
| - keywords, applying the referred schema to the instance. "$recursiveAnchor" |
961 |
| - is a helper keyword that controls how the referred schema of "$recursiveRef" |
| 960 | + keywords, applying the referenced schema to the instance. "$recursiveAnchor" |
| 961 | + is a helper keyword that controls how the referenced schema of "$recursiveRef" |
962 | 962 | is determined.
|
963 | 963 | </t>
|
964 | 964 | <t>
|
|
986 | 986 | </t>
|
987 | 987 | </section>
|
988 | 988 |
|
989 |
| - <section title='Recursive References with "$recursiveRefe" and "$recursiveAnchor"'> |
| 989 | + <section title='Recursive References with "$recursiveRef" and "$recursiveAnchor"'> |
990 | 990 | <t>
|
991 | 991 | The "$recursiveRef" and "$recursiveAnchor" keywords are used to construct
|
992 |
| - extensible recursive schemas. |
| 992 | + extensible recursive schemas. A recursive schema is one that has |
| 993 | + a reference to its own root, identified by the empty fragment |
| 994 | + URI reference ("#"). |
993 | 995 | </t>
|
994 | 996 | <t>
|
995 |
| - Intuitively, when using "$ref" or another |
996 |
| - similar keyword to combine a recursive schema with another schema (recursive |
997 |
| - or otherwise), the goal of the schema author is often to have the |
998 |
| - recursion respect that combination. The recursive reference would |
999 |
| - ideally always recurse to where the processing of the schema started. |
1000 |
| - </t> |
1001 |
| - <t> |
1002 |
| - But this is not possible with the static behavior of "$ref", wich can |
1003 |
| - only refer to the root schema of the current schema document. |
1004 |
| - More accurately, it can only refer to one location, and that location |
1005 |
| - is constrained by the static rules for resolving URI References. |
1006 |
| - </t> |
1007 |
| - <t> |
1008 |
| - This constraint leads to verbose and error-prone re-definitions of each |
1009 |
| - recursive element, as can be seen in the meta-scheme for JSON Hyper-Schema |
1010 |
| - in all prior drafts. |
| 997 | + Extending a recursive schema with "$ref" alone involves redefining all |
| 998 | + recursive references in the source schema to point to the root of the |
| 999 | + extension. This produces the correct recursive behavior in the extension, |
| 1000 | + which is that all recursion should reference the root of the extension. |
1011 | 1001 | </t>
|
1012 | 1002 | <figure>
|
1013 | 1003 | <preamble>
|
1014 |
| - Consider the following two schemas. The first (given the id "basic") |
1015 |
| - is an object with one string property and one reference property. |
1016 |
| - The reference is recursive, pointing to the root of the current |
1017 |
| - schema document. The second schema references the first, and |
1018 |
| - also describes a "things" property, which is an array of |
1019 |
| - recursive references. |
| 1004 | + Consider the following two schemas. The first schema, identified |
| 1005 | + as "original" as it is the schema to be extended, describes |
| 1006 | + an object with one string property and one recursive reference |
| 1007 | + property, "r". The second schema, identified as "extension", |
| 1008 | + references the first, and describes an additional things" property, |
| 1009 | + which is an array of recursive references. |
| 1010 | + It also repeats the description of "r" from the original schema. |
1020 | 1011 | </preamble>
|
1021 | 1012 | <artwork>
|
1022 | 1013 | <![CDATA[
|
1023 | 1014 | {
|
1024 | 1015 | "$schema": "http://json-schema.org/draft-08/schema#",
|
1025 |
| - "$id": "https://example.com/basic", |
1026 |
| - "$comment": "$ref: # referrs here from in this 'basic' file", |
| 1016 | + "$id": "https://example.com/original", |
| 1017 | +
|
1027 | 1018 | "properties": {
|
1028 | 1019 | "name": {
|
1029 | 1020 | "type": "string"
|
1030 | 1021 | },
|
1031 |
| - "recursive": { |
| 1022 | + "r": { |
1032 | 1023 | "$ref": "#"
|
1033 | 1024 | }
|
1034 | 1025 | }
|
|
1037 | 1028 | {
|
1038 | 1029 | "$schema": "http://json-schema.org/draft-08/schema#",
|
1039 | 1030 | "$id": "https://example.com/extension",
|
1040 |
| - "$comment": "$ref: # referrs here from in this 'extension' file", |
1041 |
| - "$ref": "basic", |
| 1031 | +
|
| 1032 | + "$ref": "original", |
1042 | 1033 | "properties": {
|
| 1034 | + "r": { |
| 1035 | + "$ref": "#" |
| 1036 | + }, |
1043 | 1037 | "things": {
|
1044 | 1038 | "type": "array"
|
1045 | 1039 | "items": {
|
|
1051 | 1045 | ]]>
|
1052 | 1046 | </artwork>
|
1053 | 1047 | <postamble>
|
1054 |
| - The problem is that the referred targets of the |
1055 |
| - <spanx style="verb">"$ref": "#"</spanx> |
1056 |
| - references are statically determined. Since the |
1057 |
| - <spanx style="verb">"things"</spanx> array is in the |
1058 |
| - combined schema, its referred schema is the combined |
1059 |
| - schema. But the <spanx style="verb">"recursive"</spanx> |
1060 |
| - property in the basic schema still points to the root |
1061 |
| - of that basic schema, and therefore will not see the |
1062 |
| - description of the <spanx style="verb">"things"</spanx> |
1063 |
| - property. What we want is for it to resolve |
1064 |
| - to the combined schema as well. |
| 1048 | + This apparent duplication is important because |
| 1049 | + it resolves to "https://example.com/extension#", meaning that |
| 1050 | + for instance validated against the extension schema, the value |
| 1051 | + of "r" must be valid according to the extension, and not just the |
| 1052 | + original schema as "r" was described there. |
1065 | 1053 | </postamble>
|
1066 | 1054 | </figure>
|
| 1055 | + <t> |
| 1056 | + This approach is fine for a single recursive field, but the more |
| 1057 | + complicated the original schema, the more redefinitions are necessary |
| 1058 | + in the extension. This leads to a verbose and error-prone extension, |
| 1059 | + which must be kept synchronized with the original schema if the |
| 1060 | + original changes its recursive fields. |
| 1061 | + This approach can be seen in the meta-schema for JSON Hyper-Schema |
| 1062 | + in all prior drafts. |
| 1063 | + </t> |
1067 | 1064 | <section title='Enabling Recursion with "$recursiveAnchor"'>
|
1068 | 1065 | <t>
|
1069 |
| - Since the desired behavior can seem surprising, and unpredictable, |
1070 |
| - it is important to use keywords to explicitly control all aspects |
1071 |
| - of the behavior. In order to create a recursive reference, we |
1072 |
| - must do three things: |
| 1066 | + The desired behavior is for the recursive reference, "r", in the |
| 1067 | + original schema to resolve to the original schema when that |
| 1068 | + is the only schema being used, but to resolve to the extension |
| 1069 | + schema when using the extension. Then there would be no need |
| 1070 | + to redefine the "r" property, or others like it, in the extension. |
| 1071 | + </t> |
| 1072 | + <t> |
| 1073 | + In order to create a recursive reference, we must do three things: |
1073 | 1074 | <list>
|
1074 | 1075 | <t>
|
1075 |
| - In our "basic" schema, indicate that the schema author |
| 1076 | + In our original schema, indicate that the schema author |
1076 | 1077 | intends for it to be extensible recursively.
|
1077 | 1078 | </t>
|
1078 | 1079 | <t>
|
1079 |
| - In our "extension" schema, indicate that it is intended |
| 1080 | + In our extension schema, indicate that it is intended |
1080 | 1081 | to be a recursive extension.
|
1081 | 1082 | </t>
|
1082 | 1083 | <t>
|
|
1093 | 1094 | The "$recursiveAnchor" keyword is how schema authors indicate
|
1094 | 1095 | that a schema can be extended recursively, and be a recursive
|
1095 | 1096 | schema. This keyword MAY appear in the root schema of a
|
1096 |
| - schema document, and MUST NOT appear in a subschema. |
| 1097 | + schema document, and MUST NOT appear in any subschema. |
1097 | 1098 | </t>
|
1098 | 1099 | <t>
|
1099 | 1100 | The value of "$recursiveAnchor" MUST be of type boolean, and
|
1100 | 1101 | MUST be true. The value false is reserved for possible future use.
|
1101 | 1102 | </t>
|
| 1103 | + </section> |
| 1104 | + <section title='Dynamically recursive references with "$recursiveRef"'> |
1102 | 1105 | <t>
|
1103 | 1106 | The "$recursiveRef" keyword behaves identically to "$ref", except
|
1104 |
| - that if the referred schema has "$recursiveAnchor" set to true, |
1105 |
| - then the implementation MUST check the dyanamic scope to see |
1106 |
| - if "$recursiveAnchor" had previously been set. If so, then the |
1107 |
| - referred schema is considered to be the outermost (in terms of |
1108 |
| - dynamic scope) schema object containing "$recursiveAnchor" set to true. |
| 1107 | + that if the referenced schema has "$recursiveAnchor" set to true, |
| 1108 | + then the implementation MUST examine the dynamic scope for the |
| 1109 | + outermost (first seen) schema document with "$recursiveAnchor" |
| 1110 | + set to true. If such a schema document exists, then the target |
| 1111 | + of the "$recursiveRef" MUST be set to that document's URI, in |
| 1112 | + place of the URI produced by the rules for "$ref". |
1109 | 1113 | </t>
|
1110 | 1114 | <t>
|
1111 |
| - Note that if the schema to which "$recursiveRef" referrs does not |
| 1115 | + Note that if the schema referenced by "$recursiveRef" does not |
1112 | 1116 | contain "$recursiveAnchor" set to true, or if there are no other
|
1113 | 1117 | "$recursiveAnchor" keywords set to true anywhere further back in
|
1114 | 1118 | the dynamic scope, then "$recursiveRef"'s behavior is identical
|
|
1122 | 1126 | <![CDATA[
|
1123 | 1127 | {
|
1124 | 1128 | "$schema": "http://json-schema.org/draft-08/schema#",
|
1125 |
| - "$id": "https://example.com/basic", |
| 1129 | + "$id": "https://example.com/original", |
1126 | 1130 | "$recursiveAnchor": true,
|
1127 | 1131 |
|
1128 | 1132 | "properties": {
|
1129 | 1133 | "name": {
|
1130 | 1134 | "type": "string"
|
1131 | 1135 | },
|
1132 |
| - "recursive": { |
| 1136 | + "r": { |
1133 | 1137 | "$recursiveRef": "#"
|
1134 | 1138 | }
|
1135 | 1139 | }
|
|
1140 | 1144 | "$id": "https://example.com/extension",
|
1141 | 1145 | "$recursiveAnchor": true,
|
1142 | 1146 |
|
1143 |
| - "$ref": "basic", |
| 1147 | + "$ref": "original", |
1144 | 1148 | "properties": {
|
1145 | 1149 | "things": {
|
1146 | 1150 | "type": "array"
|
|
1153 | 1157 | ]]>
|
1154 | 1158 | </artwork>
|
1155 | 1159 | <postamble>
|
1156 |
| - Now lets consider the evaluation of the "extension" schema. |
1157 |
| - Note that the "$ref": "basic" was not changed, as it works |
1158 |
| - just fine as a normals static reference. And the |
1159 |
| - "$recursiveRef" in the "extended" schema does not behave at |
1160 |
| - all differently, because the "$recursiveAnchor" in its |
1161 |
| - referred schema is the outermost "$recursiveAnchor" in the |
1162 |
| - dynamic scope. However, the "$recursiveRef" in the "basic" |
1163 |
| - schema referrs to a "$recursiveAnchor" that is not the |
1164 |
| - outermost such keyword in the dynamic scope. That is still |
1165 |
| - the "$recursiveAnchor" in the "extension" schema. |
1166 |
| - Therefore, when processing starts with the extension |
1167 |
| - schema, the "$recursiveRef" in the basic schema actually |
1168 |
| - referrs to the "extension" schema's root schema. |
| 1160 | + Note that the "r" property no longer appears in the |
| 1161 | + extension schema. Instead, all "$ref"s have been changed |
| 1162 | + to "$recursiveRef"s, and both schemas have "$recursiveAnchor" |
| 1163 | + set to true in their root schema. |
1169 | 1164 | </postamble>
|
1170 | 1165 | </figure>
|
| 1166 | + <t> |
| 1167 | + When using the original schema on its own, there is no change |
| 1168 | + in behavior. The "$recursiveRef" does lead to a schema where |
| 1169 | + "$recursiveAnchor" is set to true, but since the original schema |
| 1170 | + is the only schema document in the dynamics scope (it references |
| 1171 | + itself, and does not reference any other schema documents), the |
| 1172 | + behavior is effectively the same as "$ref". |
| 1173 | + </t> |
| 1174 | + <t> |
| 1175 | + When using the extension schema, the "$recursiveRef" within |
| 1176 | + that schema (for the array items within "things") also effectively |
| 1177 | + behaves like "$ref". The extension schema is the outermost |
| 1178 | + dynamic scope, so the reference target is not changed. |
| 1179 | + </t> |
| 1180 | + <t> |
| 1181 | + In contrast, when using the extension schema, the "$recursiveRef" |
| 1182 | + for "r" in the original schema now behaves differently. Its |
| 1183 | + initial target is the root schema of the original schema document, |
| 1184 | + which has "$recursiveAnchor" set to true. In this case, the |
| 1185 | + outermost dynamic scope that also has "$recursiveAnchor" set to |
| 1186 | + true is the extension schema. So when using the extensions schema, |
| 1187 | + "r"'s reference in the original schema will resolve to |
| 1188 | + "https://example.com/extension#", not "https://example.com/original#". |
| 1189 | + </t> |
1171 | 1190 | </section>
|
1172 | 1191 | </section>
|
1173 | 1192 |
|
|
1459 | 1478 | The application can use the schema location path to determine which
|
1460 | 1479 | values are which. The values in the feature's immediate "enabled"
|
1461 | 1480 | property schema are more specific, while the values under the re-usable
|
1462 |
| - schema that is referred to with "$ref" are more generic. The schema |
| 1481 | + schema that is referenced to with "$ref" are more generic. The schema |
1463 | 1482 | location path will show whether each value was found by crossing a
|
1464 | 1483 | "$ref" or not.
|
1465 | 1484 | </t>
|
|
0 commit comments