|
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
|
|
626 | 626 | and used with caution when defining additional keywords.
|
627 | 627 | </t>
|
628 | 628 | </section>
|
629 |
| - <section title="Referred and Referring Schemas" anchor="referred"> |
| 629 | + <section title="Referenced and Referencing Schemas" anchor="referenced"> |
630 | 630 | <t>
|
631 | 631 | As noted in <xref target="applicators" />, an applicator keyword may
|
632 | 632 | refer to a schema to be applied, rather than including it as a
|
633 | 633 | subschema in the applicator's value. In such situations, the
|
634 |
| - schema being applied is known as the referred (or referenced) schema, |
635 |
| - while the schema containing the applicator keyword is the referring |
636 |
| - (or referencing) schema. |
| 634 | + schema being applied is known as the referenced schema, while |
| 635 | + the schema containing the applicator keyword is the referencing schema. |
637 | 636 | </t>
|
638 | 637 | <t>
|
639 | 638 | While root schemas and subschemas are static concepts based on a
|
640 |
| - schema's position within a schema document, referred and referring |
| 639 | + schema's position within a schema document, referenced and referencing |
641 | 640 | schemas are dynamic. Different pairs of schemas may find themselves
|
642 |
| - in various referred and referring arrangements during the evaluation |
| 641 | + in various referenced and referencing arrangements during the evaluation |
643 | 642 | of an instance against a schema.
|
644 | 643 | </t>
|
645 | 644 | <t>
|
|
1010 | 1009 | <t>
|
1011 | 1010 | Several keywords can be used to reference a schema which is to be applied to the
|
1012 | 1011 | current instance location. "$ref" and "$recursiveRef" are an applicator
|
1013 |
| - keywords, applying the referred schema to the instance. "$recursiveAnchor" |
1014 |
| - is a helper keyword that controls how the referred schema of "$recursiveRef" |
| 1012 | + keywords, applying the referenced schema to the instance. "$recursiveAnchor" |
| 1013 | + is a helper keyword that controls how the referenced schema of "$recursiveRef" |
1015 | 1014 | is determined.
|
1016 | 1015 | </t>
|
1017 | 1016 | <t>
|
|
1039 | 1038 | </t>
|
1040 | 1039 | </section>
|
1041 | 1040 |
|
1042 |
| - <section title='Recursive References with "$recursiveRefe" and "$recursiveAnchor"'> |
| 1041 | + <section title='Recursive References with "$recursiveRef" and "$recursiveAnchor"'> |
1043 | 1042 | <t>
|
1044 | 1043 | The "$recursiveRef" and "$recursiveAnchor" keywords are used to construct
|
1045 |
| - extensible recursive schemas. |
| 1044 | + extensible recursive schemas. A recursive schema is one that has |
| 1045 | + a reference to its own root, identified by the empty fragment |
| 1046 | + URI reference ("#"). |
1046 | 1047 | </t>
|
1047 | 1048 | <t>
|
1048 |
| - Intuitively, when using "$ref" or another |
1049 |
| - similar keyword to combine a recursive schema with another schema (recursive |
1050 |
| - or otherwise), the goal of the schema author is often to have the |
1051 |
| - recursion respect that combination. The recursive reference would |
1052 |
| - ideally always recurse to where the processing of the schema started. |
1053 |
| - </t> |
1054 |
| - <t> |
1055 |
| - But this is not possible with the static behavior of "$ref", wich can |
1056 |
| - only refer to the root schema of the current schema document. |
1057 |
| - More accurately, it can only refer to one location, and that location |
1058 |
| - is constrained by the static rules for resolving URI References. |
1059 |
| - </t> |
1060 |
| - <t> |
1061 |
| - This constraint leads to verbose and error-prone re-definitions of each |
1062 |
| - recursive element, as can be seen in the meta-scheme for JSON Hyper-Schema |
1063 |
| - in all prior drafts. |
| 1049 | + Extending a recursive schema with "$ref" alone involves redefining all |
| 1050 | + recursive references in the source schema to point to the root of the |
| 1051 | + extension. This produces the correct recursive behavior in the extension, |
| 1052 | + which is that all recursion should reference the root of the extension. |
1064 | 1053 | </t>
|
1065 | 1054 | <figure>
|
1066 | 1055 | <preamble>
|
1067 |
| - Consider the following two schemas. The first (given the id "basic") |
1068 |
| - is an object with one string property and one reference property. |
1069 |
| - The reference is recursive, pointing to the root of the current |
1070 |
| - schema document. The second schema references the first, and |
1071 |
| - also describes a "things" property, which is an array of |
1072 |
| - recursive references. |
| 1056 | + Consider the following two schemas. The first schema, identified |
| 1057 | + as "original" as it is the schema to be extended, describes |
| 1058 | + an object with one string property and one recursive reference |
| 1059 | + property, "r". The second schema, identified as "extension", |
| 1060 | + references the first, and describes an additional things" property, |
| 1061 | + which is an array of recursive references. |
| 1062 | + It also repeats the description of "r" from the original schema. |
1073 | 1063 | </preamble>
|
1074 | 1064 | <artwork>
|
1075 | 1065 | <![CDATA[
|
1076 | 1066 | {
|
1077 | 1067 | "$schema": "http://json-schema.org/draft-08/schema#",
|
1078 |
| - "$id": "https://example.com/basic", |
1079 |
| - "$comment": "$ref: # referrs here from in this 'basic' file", |
| 1068 | + "$id": "https://example.com/original", |
| 1069 | +
|
1080 | 1070 | "properties": {
|
1081 | 1071 | "name": {
|
1082 | 1072 | "type": "string"
|
1083 | 1073 | },
|
1084 |
| - "recursive": { |
| 1074 | + "r": { |
1085 | 1075 | "$ref": "#"
|
1086 | 1076 | }
|
1087 | 1077 | }
|
|
1090 | 1080 | {
|
1091 | 1081 | "$schema": "http://json-schema.org/draft-08/schema#",
|
1092 | 1082 | "$id": "https://example.com/extension",
|
1093 |
| - "$comment": "$ref: # referrs here from in this 'extension' file", |
1094 |
| - "$ref": "basic", |
| 1083 | +
|
| 1084 | + "$ref": "original", |
1095 | 1085 | "properties": {
|
| 1086 | + "r": { |
| 1087 | + "$ref": "#" |
| 1088 | + }, |
1096 | 1089 | "things": {
|
1097 | 1090 | "type": "array"
|
1098 | 1091 | "items": {
|
|
1104 | 1097 | ]]>
|
1105 | 1098 | </artwork>
|
1106 | 1099 | <postamble>
|
1107 |
| - The problem is that the referred targets of the |
1108 |
| - <spanx style="verb">"$ref": "#"</spanx> |
1109 |
| - references are statically determined. Since the |
1110 |
| - <spanx style="verb">"things"</spanx> array is in the |
1111 |
| - combined schema, its referred schema is the combined |
1112 |
| - schema. But the <spanx style="verb">"recursive"</spanx> |
1113 |
| - property in the basic schema still points to the root |
1114 |
| - of that basic schema, and therefore will not see the |
1115 |
| - description of the <spanx style="verb">"things"</spanx> |
1116 |
| - property. What we want is for it to resolve |
1117 |
| - to the combined schema as well. |
| 1100 | + This apparent duplication is important because |
| 1101 | + it resolves to "https://example.com/extension#", meaning that |
| 1102 | + for instance validated against the extension schema, the value |
| 1103 | + of "r" must be valid according to the extension, and not just the |
| 1104 | + original schema as "r" was described there. |
1118 | 1105 | </postamble>
|
1119 | 1106 | </figure>
|
| 1107 | + <t> |
| 1108 | + This approach is fine for a single recursive field, but the more |
| 1109 | + complicated the original schema, the more redefinitions are necessary |
| 1110 | + in the extension. This leads to a verbose and error-prone extension, |
| 1111 | + which must be kept synchronized with the original schema if the |
| 1112 | + original changes its recursive fields. |
| 1113 | + This approach can be seen in the meta-schema for JSON Hyper-Schema |
| 1114 | + in all prior drafts. |
| 1115 | + </t> |
1120 | 1116 | <section title='Enabling Recursion with "$recursiveAnchor"'>
|
1121 | 1117 | <t>
|
1122 |
| - Since the desired behavior can seem surprising, and unpredictable, |
1123 |
| - it is important to use keywords to explicitly control all aspects |
1124 |
| - of the behavior. In order to create a recursive reference, we |
1125 |
| - must do three things: |
| 1118 | + The desired behavior is for the recursive reference, "r", in the |
| 1119 | + original schema to resolve to the original schema when that |
| 1120 | + is the only schema being used, but to resolve to the extension |
| 1121 | + schema when using the extension. Then there would be no need |
| 1122 | + to redefine the "r" property, or others like it, in the extension. |
| 1123 | + </t> |
| 1124 | + <t> |
| 1125 | + In order to create a recursive reference, we must do three things: |
1126 | 1126 | <list>
|
1127 | 1127 | <t>
|
1128 |
| - In our "basic" schema, indicate that the schema author |
| 1128 | + In our original schema, indicate that the schema author |
1129 | 1129 | intends for it to be extensible recursively.
|
1130 | 1130 | </t>
|
1131 | 1131 | <t>
|
1132 |
| - In our "extension" schema, indicate that it is intended |
| 1132 | + In our extension schema, indicate that it is intended |
1133 | 1133 | to be a recursive extension.
|
1134 | 1134 | </t>
|
1135 | 1135 | <t>
|
|
1146 | 1146 | The "$recursiveAnchor" keyword is how schema authors indicate
|
1147 | 1147 | that a schema can be extended recursively, and be a recursive
|
1148 | 1148 | schema. This keyword MAY appear in the root schema of a
|
1149 |
| - schema document, and MUST NOT appear in a subschema. |
| 1149 | + schema document, and MUST NOT appear in any subschema. |
1150 | 1150 | </t>
|
1151 | 1151 | <t>
|
1152 | 1152 | The value of "$recursiveAnchor" MUST be of type boolean, and
|
1153 | 1153 | MUST be true. The value false is reserved for possible future use.
|
1154 | 1154 | </t>
|
| 1155 | + </section> |
| 1156 | + <section title='Dynamically recursive references with "$recursiveRef"'> |
1155 | 1157 | <t>
|
1156 | 1158 | The "$recursiveRef" keyword behaves identically to "$ref", except
|
1157 |
| - that if the referred schema has "$recursiveAnchor" set to true, |
1158 |
| - then the implementation MUST check the dyanamic scope to see |
1159 |
| - if "$recursiveAnchor" had previously been set. If so, then the |
1160 |
| - referred schema is considered to be the outermost (in terms of |
1161 |
| - dynamic scope) schema object containing "$recursiveAnchor" set to true. |
| 1159 | + that if the referenced schema has "$recursiveAnchor" set to true, |
| 1160 | + then the implementation MUST examine the dynamic scope for the |
| 1161 | + outermost (first seen) schema document with "$recursiveAnchor" |
| 1162 | + set to true. If such a schema document exists, then the target |
| 1163 | + of the "$recursiveRef" MUST be set to that document's URI, in |
| 1164 | + place of the URI produced by the rules for "$ref". |
1162 | 1165 | </t>
|
1163 | 1166 | <t>
|
1164 |
| - Note that if the schema to which "$recursiveRef" referrs does not |
| 1167 | + Note that if the schema referenced by "$recursiveRef" does not |
1165 | 1168 | contain "$recursiveAnchor" set to true, or if there are no other
|
1166 | 1169 | "$recursiveAnchor" keywords set to true anywhere further back in
|
1167 | 1170 | the dynamic scope, then "$recursiveRef"'s behavior is identical
|
|
1175 | 1178 | <![CDATA[
|
1176 | 1179 | {
|
1177 | 1180 | "$schema": "http://json-schema.org/draft-08/schema#",
|
1178 |
| - "$id": "https://example.com/basic", |
| 1181 | + "$id": "https://example.com/original", |
1179 | 1182 | "$recursiveAnchor": true,
|
1180 | 1183 |
|
1181 | 1184 | "properties": {
|
1182 | 1185 | "name": {
|
1183 | 1186 | "type": "string"
|
1184 | 1187 | },
|
1185 |
| - "recursive": { |
| 1188 | + "r": { |
1186 | 1189 | "$recursiveRef": "#"
|
1187 | 1190 | }
|
1188 | 1191 | }
|
|
1193 | 1196 | "$id": "https://example.com/extension",
|
1194 | 1197 | "$recursiveAnchor": true,
|
1195 | 1198 |
|
1196 |
| - "$ref": "basic", |
| 1199 | + "$ref": "original", |
1197 | 1200 | "properties": {
|
1198 | 1201 | "things": {
|
1199 | 1202 | "type": "array"
|
|
1206 | 1209 | ]]>
|
1207 | 1210 | </artwork>
|
1208 | 1211 | <postamble>
|
1209 |
| - Now lets consider the evaluation of the "extension" schema. |
1210 |
| - Note that the "$ref": "basic" was not changed, as it works |
1211 |
| - just fine as a normals static reference. And the |
1212 |
| - "$recursiveRef" in the "extended" schema does not behave at |
1213 |
| - all differently, because the "$recursiveAnchor" in its |
1214 |
| - referred schema is the outermost "$recursiveAnchor" in the |
1215 |
| - dynamic scope. However, the "$recursiveRef" in the "basic" |
1216 |
| - schema referrs to a "$recursiveAnchor" that is not the |
1217 |
| - outermost such keyword in the dynamic scope. That is still |
1218 |
| - the "$recursiveAnchor" in the "extension" schema. |
1219 |
| - Therefore, when processing starts with the extension |
1220 |
| - schema, the "$recursiveRef" in the basic schema actually |
1221 |
| - referrs to the "extension" schema's root schema. |
| 1212 | + Note that the "r" property no longer appears in the |
| 1213 | + extension schema. Instead, all "$ref"s have been changed |
| 1214 | + to "$recursiveRef"s, and both schemas have "$recursiveAnchor" |
| 1215 | + set to true in their root schema. |
1222 | 1216 | </postamble>
|
1223 | 1217 | </figure>
|
| 1218 | + <t> |
| 1219 | + When using the original schema on its own, there is no change |
| 1220 | + in behavior. The "$recursiveRef" does lead to a schema where |
| 1221 | + "$recursiveAnchor" is set to true, but since the original schema |
| 1222 | + is the only schema document in the dynamics scope (it references |
| 1223 | + itself, and does not reference any other schema documents), the |
| 1224 | + behavior is effectively the same as "$ref". |
| 1225 | + </t> |
| 1226 | + <t> |
| 1227 | + When using the extension schema, the "$recursiveRef" within |
| 1228 | + that schema (for the array items within "things") also effectively |
| 1229 | + behaves like "$ref". The extension schema is the outermost |
| 1230 | + dynamic scope, so the reference target is not changed. |
| 1231 | + </t> |
| 1232 | + <t> |
| 1233 | + In contrast, when using the extension schema, the "$recursiveRef" |
| 1234 | + for "r" in the original schema now behaves differently. Its |
| 1235 | + initial target is the root schema of the original schema document, |
| 1236 | + which has "$recursiveAnchor" set to true. In this case, the |
| 1237 | + outermost dynamic scope that also has "$recursiveAnchor" set to |
| 1238 | + true is the extension schema. So when using the extensions schema, |
| 1239 | + "r"'s reference in the original schema will resolve to |
| 1240 | + "https://example.com/extension#", not "https://example.com/original#". |
| 1241 | + </t> |
1224 | 1242 | </section>
|
1225 | 1243 | </section>
|
1226 | 1244 |
|
|
1512 | 1530 | The application can use the schema location path to determine which
|
1513 | 1531 | values are which. The values in the feature's immediate "enabled"
|
1514 | 1532 | property schema are more specific, while the values under the re-usable
|
1515 |
| - schema that is referred to with "$ref" are more generic. The schema |
| 1533 | + schema that is referenced to with "$ref" are more generic. The schema |
1516 | 1534 | location path will show whether each value was found by crossing a
|
1517 | 1535 | "$ref" or not.
|
1518 | 1536 | </t>
|
|
0 commit comments