diff --git a/src/main/java/com/networknt/schema/JsonSchemaFactory.java b/src/main/java/com/networknt/schema/JsonSchemaFactory.java index f01b7209d..0f3a5ecd1 100644 --- a/src/main/java/com/networknt/schema/JsonSchemaFactory.java +++ b/src/main/java/com/networknt/schema/JsonSchemaFactory.java @@ -50,8 +50,6 @@ public static class Builder { private URNFactory urnFactory; private final Map jsonMetaSchemas = new HashMap(); private final Map uriMap = new HashMap(); - private boolean forceHttps = true; - private boolean removeEmptyFragmentSuffix = true; private boolean enableUriSchemaCache = true; private final CompositeURITranslator uriTranslators = new CompositeURITranslator(); @@ -129,13 +127,13 @@ public Builder uriFetcher(final URIFetcher uriFetcher, final Iterable sc } public Builder addMetaSchema(final JsonMetaSchema jsonMetaSchema) { - this.jsonMetaSchemas.put(jsonMetaSchema.getUri(), jsonMetaSchema); + this.jsonMetaSchemas.put(normalizeMetaSchemaUri(jsonMetaSchema.getUri()) , jsonMetaSchema); return this; } public Builder addMetaSchemas(final Collection jsonMetaSchemas) { for (JsonMetaSchema jsonMetaSchema : jsonMetaSchemas) { - this.jsonMetaSchemas.put(jsonMetaSchema.getUri(), jsonMetaSchema); + addMetaSchema(jsonMetaSchema); } return this; } @@ -163,13 +161,21 @@ public Builder addUrnFactory(URNFactory urnFactory) { return this; } + /** + * @deprecated No longer necessary. + * @param forceHttps ignored. + * @return this builder. + */ public Builder forceHttps(boolean forceHttps) { - this.forceHttps = forceHttps; return this; } + /** + * @deprecated No longer necessary. + * @param removeEmptyFragmentSuffix ignored. + * @return this builder. + */ public Builder removeEmptyFragmentSuffix(boolean removeEmptyFragmentSuffix) { - this.removeEmptyFragmentSuffix = removeEmptyFragmentSuffix; return this; } @@ -189,8 +195,6 @@ public JsonSchemaFactory build() { urnFactory, jsonMetaSchemas, uriMap, - forceHttps, - removeEmptyFragmentSuffix, enableUriSchemaCache, uriTranslators ); @@ -207,8 +211,6 @@ public JsonSchemaFactory build() { private final Map jsonMetaSchemas; private final Map uriMap; private final ConcurrentMap uriSchemaCache = new ConcurrentHashMap(); - private final boolean forceHttps; - private final boolean removeEmptyFragmentSuffix; private final boolean enableUriSchemaCache; @@ -221,8 +223,6 @@ private JsonSchemaFactory( final URNFactory urnFactory, final Map jsonMetaSchemas, final Map uriMap, - final boolean forceHttps, - final boolean removeEmptyFragmentSuffix, final boolean enableUriSchemaCache, final CompositeURITranslator uriTranslators) { if (jsonMapper == null) { @@ -237,7 +237,7 @@ private JsonSchemaFactory( throw new IllegalArgumentException("URIFetcher must not be null"); } else if (jsonMetaSchemas == null || jsonMetaSchemas.isEmpty()) { throw new IllegalArgumentException("Json Meta Schemas must not be null or empty"); - } else if (jsonMetaSchemas.get(defaultMetaSchemaURI) == null) { + } else if (jsonMetaSchemas.get(normalizeMetaSchemaUri(defaultMetaSchemaURI)) == null) { throw new IllegalArgumentException("Meta Schema for default Meta Schema URI must be provided"); } else if (uriMap == null) { throw new IllegalArgumentException("URL Mappings must not be null"); @@ -252,8 +252,6 @@ private JsonSchemaFactory( this.urnFactory = urnFactory; this.jsonMetaSchemas = jsonMetaSchemas; this.uriMap = uriMap; - this.forceHttps = forceHttps; - this.removeEmptyFragmentSuffix = removeEmptyFragmentSuffix; this.enableUriSchemaCache = enableUriSchemaCache; this.uriTranslators = uriTranslators; } @@ -348,7 +346,7 @@ private JsonMetaSchema findMetaSchemaForSchema(final JsonNode schemaNode) { if (uriNode != null && !uriNode.isNull() && !uriNode.isTextual()) { throw new JsonSchemaException("Unknown MetaSchema: " + uriNode.toString()); } - final String uri = uriNode == null || uriNode.isNull() ? defaultMetaSchemaURI : normalizeMetaSchemaUri(uriNode.textValue(), forceHttps, removeEmptyFragmentSuffix); + final String uri = uriNode == null || uriNode.isNull() ? defaultMetaSchemaURI : normalizeMetaSchemaUri(uriNode.textValue()); final JsonMetaSchema jsonMetaSchema = jsonMetaSchemas.computeIfAbsent(uri, this::fromId); return jsonMetaSchema; } @@ -504,17 +502,12 @@ private boolean isYaml(final URI schemaUri) { return (".yml".equals(extension) || ".yaml".equals(extension)); } - static protected String normalizeMetaSchemaUri(String u, boolean forceHttps, boolean removeEmptyFragmentSuffix) { + static protected String normalizeMetaSchemaUri(String u) { try { URI uri = new URI(u); - String scheme = forceHttps ? "https" : uri.getScheme(); - URI newUri = new URI(scheme, uri.getUserInfo(), uri.getHost(), uri.getPort(), uri.getPath(), null, null); + URI newUri = new URI("https", uri.getUserInfo(), uri.getHost(), uri.getPort(), uri.getPath(), null, null); - if (!removeEmptyFragmentSuffix && u.endsWith("#")) { - return newUri + "#"; - } else { - return newUri.toString(); - } + return newUri.toString(); } catch (URISyntaxException e) { throw new JsonSchemaException("Wrong MetaSchema URI: " + u); } diff --git a/src/main/java/com/networknt/schema/SpecVersionDetector.java b/src/main/java/com/networknt/schema/SpecVersionDetector.java index 452703ac4..63bcb1083 100644 --- a/src/main/java/com/networknt/schema/SpecVersionDetector.java +++ b/src/main/java/com/networknt/schema/SpecVersionDetector.java @@ -58,12 +58,8 @@ public static VersionFlag detect(JsonNode jsonNode) { public static Optional detectOptionalVersion(JsonNode jsonNode) { return Optional.ofNullable(jsonNode.get(SCHEMA_TAG)).map(schemaTag -> { - final boolean forceHttps = true; - final boolean removeEmptyFragmentSuffix = true; - String schemaTagValue = schemaTag.asText(); - String schemaUri = JsonSchemaFactory.normalizeMetaSchemaUri(schemaTagValue, forceHttps, - removeEmptyFragmentSuffix); + String schemaUri = JsonSchemaFactory.normalizeMetaSchemaUri(schemaTagValue); return VersionFlag.fromId(schemaUri) .orElseThrow(() -> new JsonSchemaException("'" + schemaTagValue + "' is unrecognizable schema")); diff --git a/src/test/java/com/networknt/schema/Issue832Test.java b/src/test/java/com/networknt/schema/Issue832Test.java new file mode 100644 index 000000000..1235ddffe --- /dev/null +++ b/src/test/java/com/networknt/schema/Issue832Test.java @@ -0,0 +1,59 @@ +package com.networknt.schema; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.networknt.schema.format.AbstractFormat; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +public class Issue832Test { + private class NoMatchFormat extends AbstractFormat { + public NoMatchFormat() { + super("no_match", "always fail match"); + } + + @Override + public boolean matches(String value) { + return false; + } + } + + private JsonSchemaFactory buildV7PlusNoFormatSchemaFactory() { + List formats; + formats = new ArrayList<>(); + formats.add(new NoMatchFormat()); + + JsonMetaSchema jsonMetaSchema = JsonMetaSchema.builder( + JsonMetaSchema.getV7().getUri(), + JsonMetaSchema.getV7()) + .addFormats(formats) + .build(); + return new JsonSchemaFactory.Builder().defaultMetaSchemaURI(jsonMetaSchema.getUri()).addMetaSchema(jsonMetaSchema).build(); + } + + protected JsonNode getJsonNodeFromStreamContent(InputStream content) throws IOException { + ObjectMapper mapper = new ObjectMapper(); + return mapper.readTree(content); + } + + @Test + public void testV7WithNonMatchingCustomFormat() throws IOException { + String schemaPath = "/schema/issue832-v7.json"; + String dataPath = "/data/issue832.json"; + InputStream schemaInputStream = getClass().getResourceAsStream(schemaPath); + JsonSchemaFactory factory = buildV7PlusNoFormatSchemaFactory(); + JsonSchema schema = factory.getSchema(schemaInputStream); + InputStream dataInputStream = getClass().getResourceAsStream(dataPath); + JsonNode node = getJsonNodeFromStreamContent(dataInputStream); + Set errors = schema.validate(node); + // Both the custom no_match format and the standard email format should fail. + // This ensures that both the standard and custom formatters have been invoked. + Assertions.assertEquals(2, errors.size()); + } +} diff --git a/src/test/java/com/networknt/schema/UnknownMetaSchemaTest.java b/src/test/java/com/networknt/schema/UnknownMetaSchemaTest.java index 601119d84..7e6a6d49d 100644 --- a/src/test/java/com/networknt/schema/UnknownMetaSchemaTest.java +++ b/src/test/java/com/networknt/schema/UnknownMetaSchemaTest.java @@ -59,8 +59,6 @@ public void testSchema3() throws IOException { @Test public void testNormalize() throws JsonSchemaException { - final boolean forceHttps = true; - final boolean removeEmptyFragmentSuffix = true; String uri01 = "http://json-schema.org/draft-07/schema"; String uri02 = "http://json-schema.org/draft-07/schema#"; @@ -68,44 +66,10 @@ public void testNormalize() throws JsonSchemaException { String uri04 = "http://json-schema.org/draft-07/schema?key=value&key2=value2"; String expected = "https://json-schema.org/draft-07/schema"; - Assertions.assertEquals(expected, JsonSchemaFactory.normalizeMetaSchemaUri(uri01, forceHttps, removeEmptyFragmentSuffix)); - Assertions.assertEquals(expected, JsonSchemaFactory.normalizeMetaSchemaUri(uri02, forceHttps, removeEmptyFragmentSuffix)); - Assertions.assertEquals(expected, JsonSchemaFactory.normalizeMetaSchemaUri(uri03, forceHttps, removeEmptyFragmentSuffix)); - Assertions.assertEquals(expected, JsonSchemaFactory.normalizeMetaSchemaUri(uri04, forceHttps, removeEmptyFragmentSuffix)); - - } - - @Test - public void testNormalizeForceHttpsDisabled() throws JsonSchemaException { - final boolean forceHttps = false; - final boolean removeEmptyFragmentSuffix = true; - - String uri01 = "http://json-schema.org/draft-07/schema"; - String uri02 = "http://json-schema.org/draft-07/schema#"; - String uri03 = "http://json-schema.org/draft-07/schema?key=value"; - String uri04 = "http://json-schema.org/draft-07/schema?key=value&key2=value2"; - String expected = "http://json-schema.org/draft-07/schema"; - - Assertions.assertEquals(expected, JsonSchemaFactory.normalizeMetaSchemaUri(uri01, forceHttps, removeEmptyFragmentSuffix)); - Assertions.assertEquals(expected, JsonSchemaFactory.normalizeMetaSchemaUri(uri02, forceHttps, removeEmptyFragmentSuffix)); - Assertions.assertEquals(expected, JsonSchemaFactory.normalizeMetaSchemaUri(uri03, forceHttps, removeEmptyFragmentSuffix)); - Assertions.assertEquals(expected, JsonSchemaFactory.normalizeMetaSchemaUri(uri04, forceHttps, removeEmptyFragmentSuffix)); - - } - - @Test - public void testNormalizeRemovingEmptyFragmentSuffixDisabled() throws JsonSchemaException { - final boolean forceHttps = true; - final boolean removeEmptyFragmentSuffix = false; - - String uri01 = "http://json-schema.org/draft-07/schema#"; - String uri02 = "http://json-schema.org/draft-07/schema?key=value#"; - String uri03 = "http://json-schema.org/draft-07/schema?key=value&key2=value2#"; - String expected = "https://json-schema.org/draft-07/schema#"; - - Assertions.assertEquals(expected, JsonSchemaFactory.normalizeMetaSchemaUri(uri01, forceHttps, removeEmptyFragmentSuffix)); - Assertions.assertEquals(expected, JsonSchemaFactory.normalizeMetaSchemaUri(uri02, forceHttps, removeEmptyFragmentSuffix)); - Assertions.assertEquals(expected, JsonSchemaFactory.normalizeMetaSchemaUri(uri03, forceHttps, removeEmptyFragmentSuffix)); + Assertions.assertEquals(expected, JsonSchemaFactory.normalizeMetaSchemaUri(uri01)); + Assertions.assertEquals(expected, JsonSchemaFactory.normalizeMetaSchemaUri(uri02)); + Assertions.assertEquals(expected, JsonSchemaFactory.normalizeMetaSchemaUri(uri03)); + Assertions.assertEquals(expected, JsonSchemaFactory.normalizeMetaSchemaUri(uri04)); } } diff --git a/src/test/resources/data/issue832.json b/src/test/resources/data/issue832.json new file mode 100644 index 000000000..c84fe2332 --- /dev/null +++ b/src/test/resources/data/issue832.json @@ -0,0 +1,4 @@ +{ + "foo": "does not match", + "contact": "not an email address" +} diff --git a/src/test/resources/schema/issue832-v7.json b/src/test/resources/schema/issue832-v7.json new file mode 100644 index 000000000..94044736b --- /dev/null +++ b/src/test/resources/schema/issue832-v7.json @@ -0,0 +1,16 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "foo": { + "type": "string", + "format": "no_match" + }, + "contact": { + "type": "string", + "format": "email" + } + }, + "required": ["foo", "contact"], + "type": "object" +}