Skip to content

Commit 40df912

Browse files
author
Matti Hansson
committed
Add support for subschema references in getSchema(URI) (networknt#619)
1 parent 7b48580 commit 40df912

File tree

3 files changed

+38
-10
lines changed

3 files changed

+38
-10
lines changed

src/main/java/com/networknt/schema/JsonSchema.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
import java.io.UnsupportedEncodingException;
2828
import java.net.URI;
29+
import java.net.URISyntaxException;
2930
import java.net.URLDecoder;
3031
import java.util.*;
3132
import java.util.Map.Entry;
@@ -53,7 +54,6 @@ public class JsonSchema extends BaseJsonValidator {
5354
* 'id' would still be able to specify an absolute uri.
5455
*/
5556
private final URI currentUri;
56-
5757
private JsonValidator requiredValidator = null;
5858

5959
private JsonValidator unevaluatedPropertiesValidator = null;
@@ -80,7 +80,7 @@ private JsonSchema(ValidationContext validationContext, String schemaPath, URI c
8080
validationContext.getConfig() != null ? validationContext.getConfig().getApplyDefaultsStrategy() : null);
8181
this.validationContext = validationContext;
8282
this.metaSchema = validationContext.getMetaSchema();
83-
this.currentUri = this.combineCurrentUriWithIds(currentUri, schemaNode);
83+
this.currentUri = currentUri = this.combineCurrentUriWithIds(currentUri, schemaNode);
8484
if (validationContext.getConfig() != null) {
8585
keywordWalkListenerRunner = new DefaultKeywordWalkListenerRunner(this.validationContext.getConfig().getKeywordWalkListenersMap());
8686
if (validationContext.getConfig().isOpenAPI3StyleDiscriminators()) {
@@ -98,6 +98,13 @@ private JsonSchema(ValidationContext validationContext, String schemaPath, URI c
9898
if (fragmentSchemaNode == null) {
9999
throw new JsonSchemaException("Fragment " + fragment + " cannot be resolved");
100100
}
101+
URI currentUriWithoutFragment;
102+
try {
103+
currentUriWithoutFragment = new URI(currentUri.getScheme(), currentUri.getSchemeSpecificPart(), null);
104+
} catch (URISyntaxException ex) {
105+
throw new JsonSchemaException("Unable to create URI without fragment from " + currentUri + ": " + ex.getMessage());
106+
}
107+
this.parentSchema = new JsonSchema(this.validationContext, this.schemaPath, currentUriWithoutFragment, this.schemaNode, this.parentSchema);
101108
this.schemaPath = fragment;
102109
this.schemaNode = fragmentSchemaNode;
103110
}

src/test/java/com/networknt/schema/Issue619Test.java

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public void setup() throws Exception {
4040

4141
@Test
4242
public void checkThatBundledSchemaLoadsAndValidatesCorrectly() throws Exception {
43-
JsonSchema rootSchema = factory.getSchema(new URI("resource:data/issue619.json"));
43+
JsonSchema rootSchema = factory.getSchema(new URI("resource:schema/issue619.json"));
4444

4545
assertTrue(rootSchema.validate(one).isEmpty());
4646
assertTrue(rootSchema.validate(two).isEmpty());
@@ -49,7 +49,7 @@ public void checkThatBundledSchemaLoadsAndValidatesCorrectly() throws Exception
4949

5050
@Test
5151
public void checkThatSchemaThatReferencesBundledSchemaLoadsAndValidatesCorrectly() {
52-
JsonSchema referencingRootSchema = factory.getSchema("{ \"$ref\": \"resource:data/issue619.json\" }");
52+
JsonSchema referencingRootSchema = factory.getSchema("{ \"$ref\": \"resource:schema/issue619.json\" }");
5353

5454
assertTrue(referencingRootSchema.validate(one).isEmpty());
5555
assertTrue(referencingRootSchema.validate(two).isEmpty());
@@ -58,7 +58,7 @@ public void checkThatSchemaThatReferencesBundledSchemaLoadsAndValidatesCorrectly
5858

5959
@Test
6060
public void checkThatUriThatPointsToEmptyFragmentLoadsAndValidatesCorrectly() throws Exception {
61-
JsonSchema rootSchema = factory.getSchema(new URI("resource:data/issue619.json#"));
61+
JsonSchema rootSchema = factory.getSchema(new URI("resource:schema/issue619.json#"));
6262

6363
assertTrue(rootSchema.validate(one).isEmpty());
6464
assertTrue(rootSchema.validate(two).isEmpty());
@@ -67,7 +67,7 @@ public void checkThatUriThatPointsToEmptyFragmentLoadsAndValidatesCorrectly() th
6767

6868
@Test
6969
public void checkThatSchemaThatReferencesEmptyFragmentLoadsAndValidatesCorrectly() {
70-
JsonSchema referencingRootSchema = factory.getSchema("{ \"$ref\": \"resource:data/issue619.json#\" }");
70+
JsonSchema referencingRootSchema = factory.getSchema("{ \"$ref\": \"resource:schema/issue619.json#\" }");
7171

7272
assertTrue(referencingRootSchema.validate(one).isEmpty());
7373
assertTrue(referencingRootSchema.validate(two).isEmpty());
@@ -76,7 +76,7 @@ public void checkThatSchemaThatReferencesEmptyFragmentLoadsAndValidatesCorrectly
7676

7777
@Test
7878
public void loadingSchemaWithUriThatPointsToOneShouldOnlyValidateOne() throws Exception {
79-
JsonSchema oneSchema = factory.getSchema(new URI("resource:data/issue619.json#/definitions/one"));
79+
JsonSchema oneSchema = factory.getSchema(new URI("resource:schema/issue619.json#/definitions/one"));
8080

8181
assertTrue(oneSchema.validate(one).isEmpty());
8282
assertFalse(oneSchema.validate(two).isEmpty());
@@ -85,13 +85,31 @@ public void loadingSchemaWithUriThatPointsToOneShouldOnlyValidateOne() throws Ex
8585

8686
@Test
8787
public void referencingSchemaWithUriThatPointsToTwoShouldOnlyValidateTwo() {
88-
JsonSchema referencingTwoSchema = factory.getSchema("{ \"$ref\": \"resource:data/issue619.json#/definitions/two\" }");
88+
JsonSchema referencingTwoSchema = factory.getSchema("{ \"$ref\": \"resource:schema/issue619.json#/definitions/two\" }");
8989

9090
assertFalse(referencingTwoSchema.validate(one).isEmpty());
9191
assertTrue(referencingTwoSchema.validate(two).isEmpty());
9292
assertFalse(referencingTwoSchema.validate(three).isEmpty());
9393
}
9494

95+
@Test
96+
public void loadingSchemaWithUriThatPointsToNodeThatInTurnReferencesOneShouldOnlyValidateOne() throws Exception {
97+
JsonSchema oneSchema = factory.getSchema(new URI("resource:schema/issue619.json#/definitions/refToOne"));
98+
99+
assertTrue(oneSchema.validate(one).isEmpty());
100+
assertFalse(oneSchema.validate(two).isEmpty());
101+
assertFalse(oneSchema.validate(three).isEmpty());
102+
}
103+
104+
@Test
105+
public void referencingSchemaWithUriThatPointsToNodeThatInTurnReferencesOneShouldOnlyValidateOne() {
106+
JsonSchema referencingTwoSchema = factory.getSchema("{ \"$ref\": \"resource:schema/issue619.json#/definitions/refToOne\" }");
107+
108+
assertTrue(referencingTwoSchema.validate(one).isEmpty());
109+
assertFalse(referencingTwoSchema.validate(two).isEmpty());
110+
assertFalse(referencingTwoSchema.validate(three).isEmpty());
111+
}
112+
95113
@Test
96114
public void loadingSchemaWithUriThatPointsToSchemaThatDoesNotExistShouldFail() {
97115
assertThrows(JsonSchemaException.class, () -> factory.getSchema(new URI("resource:data/schema-that-does-not-exist.json#/definitions/something")));
@@ -106,12 +124,12 @@ public void referencingSchemaWithUriThatPointsToSchemaThatDoesNotExistShouldFail
106124

107125
@Test
108126
public void loadingSchemaWithUriThatPointsToNodeThatDoesNotExistShouldFail() {
109-
assertThrows(JsonSchemaException.class, () -> factory.getSchema(new URI("resource:data/issue619.json#/definitions/node-that-does-not-exist")));
127+
assertThrows(JsonSchemaException.class, () -> factory.getSchema(new URI("resource:schema/issue619.json#/definitions/node-that-does-not-exist")));
110128
}
111129

112130
@Test
113131
public void referencingSchemaWithUriThatPointsToNodeThatDoesNotExistShouldFail() {
114-
JsonSchema referencingNonexistentSchema = factory.getSchema("{ \"$ref\": \"resource:data/issue619.json#/definitions/node-that-does-not-exist\" }");
132+
JsonSchema referencingNonexistentSchema = factory.getSchema("{ \"$ref\": \"resource:schema/issue619.json#/definitions/node-that-does-not-exist\" }");
115133

116134
assertThrows(JsonSchemaException.class, () -> referencingNonexistentSchema.validate(one));
117135
}

src/test/resources/data/issue619.json renamed to src/test/resources/schema/issue619.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
"two": {
1717
"type": "integer",
1818
"enum": [2]
19+
},
20+
"refToOne": {
21+
"$ref": "#/definitions/one"
1922
}
2023
}
2124
}

0 commit comments

Comments
 (0)