Skip to content

Commit 67bff81

Browse files
authored
Preserve # suffix during metaschema URI normalization (#519)
* Add test reproducing issue #518 * fixes #518 add flag for preserving '#' during metaschema URI normalisation
1 parent 035f63c commit 67bff81

File tree

5 files changed

+100
-11
lines changed

5 files changed

+100
-11
lines changed

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

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public static class Builder {
4848
private final Map<String, JsonMetaSchema> jsonMetaSchemas = new HashMap<String, JsonMetaSchema>();
4949
private final Map<String, String> uriMap = new HashMap<String, String>();
5050
private boolean forceHttps = true;
51-
51+
private boolean removeEmptyFragmentSuffix = true;
5252

5353
public Builder() {
5454
// Adds support for creating {@link URL}s.
@@ -145,6 +145,11 @@ public Builder forceHttps(boolean forceHttps) {
145145
return this;
146146
}
147147

148+
public Builder removeEmptyFragmentSuffix(boolean removeEmptyFragmentSuffix) {
149+
this.removeEmptyFragmentSuffix = removeEmptyFragmentSuffix;
150+
return this;
151+
}
152+
148153
public JsonSchemaFactory build() {
149154
// create builtin keywords with (custom) formats.
150155
return new JsonSchemaFactory(
@@ -155,7 +160,8 @@ public JsonSchemaFactory build() {
155160
urnFactory,
156161
jsonMetaSchemas,
157162
uriMap,
158-
forceHttps
163+
forceHttps,
164+
removeEmptyFragmentSuffix
159165
);
160166
}
161167
}
@@ -169,6 +175,7 @@ public JsonSchemaFactory build() {
169175
private final Map<String, String> uriMap;
170176
private final ConcurrentMap<URI, JsonSchema> uriSchemaCache = new ConcurrentHashMap<URI, JsonSchema>();
171177
private final boolean forceHttps;
178+
private final boolean removeEmptyFragmentSuffix;
172179

173180

174181
private JsonSchemaFactory(
@@ -179,7 +186,8 @@ private JsonSchemaFactory(
179186
final URNFactory urnFactory,
180187
final Map<String, JsonMetaSchema> jsonMetaSchemas,
181188
final Map<String, String> uriMap,
182-
final boolean forceHttps) {
189+
final boolean forceHttps,
190+
final boolean removeEmptyFragmentSuffix) {
183191
if (mapper == null) {
184192
throw new IllegalArgumentException("ObjectMapper must not be null");
185193
} else if (defaultMetaSchemaURI == null || defaultMetaSchemaURI.trim().isEmpty()) {
@@ -203,6 +211,7 @@ private JsonSchemaFactory(
203211
this.jsonMetaSchemas = jsonMetaSchemas;
204212
this.uriMap = uriMap;
205213
this.forceHttps = forceHttps;
214+
this.removeEmptyFragmentSuffix = removeEmptyFragmentSuffix;
206215
}
207216

208217
/**
@@ -281,7 +290,7 @@ protected ValidationContext createValidationContext(final JsonNode schemaNode) {
281290

282291
private JsonMetaSchema findMetaSchemaForSchema(final JsonNode schemaNode) {
283292
final JsonNode uriNode = schemaNode.get("$schema");
284-
final String uri = uriNode == null || uriNode.isNull() ? defaultMetaSchemaURI : normalizeMetaSchemaUri(uriNode.textValue(), forceHttps);
293+
final String uri = uriNode == null || uriNode.isNull() ? defaultMetaSchemaURI : normalizeMetaSchemaUri(uriNode.textValue(), forceHttps, removeEmptyFragmentSuffix);
285294
final JsonMetaSchema jsonMetaSchema = jsonMetaSchemas.get(uri);
286295
if (jsonMetaSchema == null) {
287296
throw new JsonSchemaException("Unknown MetaSchema: " + uri);
@@ -409,12 +418,17 @@ private boolean idMatchesSourceUri(final JsonMetaSchema metaSchema, final JsonNo
409418
return result;
410419
}
411420

412-
static protected String normalizeMetaSchemaUri(String u, boolean forceHttps) {
421+
static protected String normalizeMetaSchemaUri(String u, boolean forceHttps, boolean removeEmptyFragmentSuffix) {
413422
try {
414423
URI uri = new URI(u);
415424
String scheme = forceHttps ? "https" : uri.getScheme();
416425
URI newUri = new URI(scheme, uri.getUserInfo(), uri.getHost(), uri.getPort(), uri.getPath(), null, null);
417-
return newUri.toString();
426+
427+
if (!removeEmptyFragmentSuffix && u.endsWith("#")) {
428+
return newUri + "#";
429+
} else {
430+
return newUri.toString();
431+
}
418432
} catch (URISyntaxException e) {
419433
throw new JsonSchemaException("Wrong MetaSchema URI: " + u);
420434
}

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,10 @@ public static SpecVersion.VersionFlag detect(JsonNode jsonNode) {
3939
if (!jsonNode.has(SCHEMA_TAG))
4040
throw new JsonSchemaException("Schema tag not present");
4141

42-
String schemaUri = JsonSchemaFactory.normalizeMetaSchemaUri(jsonNode.get(SCHEMA_TAG).asText(), true);
42+
final boolean forceHttps = true;
43+
final boolean removeEmptyFragmentSuffix = true;
44+
45+
String schemaUri = JsonSchemaFactory.normalizeMetaSchemaUri(jsonNode.get(SCHEMA_TAG).asText(), forceHttps, removeEmptyFragmentSuffix);
4346
if (schemaUri.equals(JsonMetaSchema.getV4().getUri()))
4447
return SpecVersion.VersionFlag.V4;
4548
else if (schemaUri.equals(JsonMetaSchema.getV6().getUri()))
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.networknt.schema;
2+
3+
import org.junit.jupiter.api.Assertions;
4+
import org.junit.jupiter.api.Test;
5+
6+
import java.io.InputStream;
7+
8+
public class Issue518Test {
9+
private static final JsonMetaSchema igluMetaSchema =
10+
JsonMetaSchema
11+
.builder("http://iglucentral.com/schemas/com.snowplowanalytics.self-desc/schema/jsonschema/1-0-0#", JsonMetaSchema.getV7())
12+
.build();
13+
14+
private static final JsonSchemaFactory FACTORY =
15+
JsonSchemaFactory
16+
.builder(JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V7))
17+
.addMetaSchema(igluMetaSchema)
18+
.forceHttps(false)
19+
.removeEmptyFragmentSuffix(false)
20+
.build();
21+
22+
@Test
23+
public void testPreservingEmptyFragmentSuffix() {
24+
String schemaPath = "/schema/issue518-v7.json";
25+
InputStream schemaInputStream = getClass().getResourceAsStream(schemaPath);
26+
JsonSchema schema = FACTORY.getSchema(schemaInputStream);
27+
28+
Assertions.assertNotNull(schema);
29+
}
30+
}

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

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,15 +59,53 @@ public void testSchema3() throws IOException {
5959

6060
@Test
6161
public void testNormalize() throws JsonSchemaException {
62+
final boolean forceHttps = true;
63+
final boolean removeEmptyFragmentSuffix = true;
64+
6265
String uri01 = "http://json-schema.org/draft-07/schema";
6366
String uri02 = "http://json-schema.org/draft-07/schema#";
6467
String uri03 = "http://json-schema.org/draft-07/schema?key=value";
6568
String uri04 = "http://json-schema.org/draft-07/schema?key=value&key2=value2";
6669
String expected = "https://json-schema.org/draft-07/schema";
67-
Assertions.assertEquals(expected, JsonSchemaFactory.normalizeMetaSchemaUri(uri01, true));
68-
Assertions.assertEquals(expected, JsonSchemaFactory.normalizeMetaSchemaUri(uri02, true));
69-
Assertions.assertEquals(expected, JsonSchemaFactory.normalizeMetaSchemaUri(uri03, true));
70-
Assertions.assertEquals(expected, JsonSchemaFactory.normalizeMetaSchemaUri(uri04, true));
70+
71+
Assertions.assertEquals(expected, JsonSchemaFactory.normalizeMetaSchemaUri(uri01, forceHttps, removeEmptyFragmentSuffix));
72+
Assertions.assertEquals(expected, JsonSchemaFactory.normalizeMetaSchemaUri(uri02, forceHttps, removeEmptyFragmentSuffix));
73+
Assertions.assertEquals(expected, JsonSchemaFactory.normalizeMetaSchemaUri(uri03, forceHttps, removeEmptyFragmentSuffix));
74+
Assertions.assertEquals(expected, JsonSchemaFactory.normalizeMetaSchemaUri(uri04, forceHttps, removeEmptyFragmentSuffix));
75+
76+
}
77+
78+
@Test
79+
public void testNormalizeForceHttpsDisabled() throws JsonSchemaException {
80+
final boolean forceHttps = false;
81+
final boolean removeEmptyFragmentSuffix = true;
82+
83+
String uri01 = "http://json-schema.org/draft-07/schema";
84+
String uri02 = "http://json-schema.org/draft-07/schema#";
85+
String uri03 = "http://json-schema.org/draft-07/schema?key=value";
86+
String uri04 = "http://json-schema.org/draft-07/schema?key=value&key2=value2";
87+
String expected = "http://json-schema.org/draft-07/schema";
88+
89+
Assertions.assertEquals(expected, JsonSchemaFactory.normalizeMetaSchemaUri(uri01, forceHttps, removeEmptyFragmentSuffix));
90+
Assertions.assertEquals(expected, JsonSchemaFactory.normalizeMetaSchemaUri(uri02, forceHttps, removeEmptyFragmentSuffix));
91+
Assertions.assertEquals(expected, JsonSchemaFactory.normalizeMetaSchemaUri(uri03, forceHttps, removeEmptyFragmentSuffix));
92+
Assertions.assertEquals(expected, JsonSchemaFactory.normalizeMetaSchemaUri(uri04, forceHttps, removeEmptyFragmentSuffix));
93+
94+
}
95+
96+
@Test
97+
public void testNormalizeRemovingEmptyFragmentSuffixDisabled() throws JsonSchemaException {
98+
final boolean forceHttps = true;
99+
final boolean removeEmptyFragmentSuffix = false;
100+
101+
String uri01 = "http://json-schema.org/draft-07/schema#";
102+
String uri02 = "http://json-schema.org/draft-07/schema?key=value#";
103+
String uri03 = "http://json-schema.org/draft-07/schema?key=value&key2=value2#";
104+
String expected = "https://json-schema.org/draft-07/schema#";
105+
106+
Assertions.assertEquals(expected, JsonSchemaFactory.normalizeMetaSchemaUri(uri01, forceHttps, removeEmptyFragmentSuffix));
107+
Assertions.assertEquals(expected, JsonSchemaFactory.normalizeMetaSchemaUri(uri02, forceHttps, removeEmptyFragmentSuffix));
108+
Assertions.assertEquals(expected, JsonSchemaFactory.normalizeMetaSchemaUri(uri03, forceHttps, removeEmptyFragmentSuffix));
71109

72110
}
73111
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"$schema": "http://iglucentral.com/schemas/com.snowplowanalytics.self-desc/schema/jsonschema/1-0-0#",
3+
"type": "object"
4+
}

0 commit comments

Comments
 (0)