Skip to content

Commit dcd6749

Browse files
authored
Add option to disable uri schema cache in JsonSchemaFactory (#679)
* Add config to opt out of json schema cache * cacheSchema to enableUriSchemaCache
1 parent d22b587 commit dcd6749

File tree

2 files changed

+92
-4
lines changed

2 files changed

+92
-4
lines changed

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

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ public static class Builder {
5151
private final Map<String, String> uriMap = new HashMap<String, String>();
5252
private boolean forceHttps = true;
5353
private boolean removeEmptyFragmentSuffix = true;
54+
private boolean enableUriSchemaCache = true;
5455

5556
public Builder() {
5657
// Adds support for creating {@link URL}s.
@@ -157,6 +158,11 @@ public Builder removeEmptyFragmentSuffix(boolean removeEmptyFragmentSuffix) {
157158
return this;
158159
}
159160

161+
public Builder enableUriSchemaCache(boolean enableUriSchemaCache) {
162+
this.enableUriSchemaCache = enableUriSchemaCache;
163+
return this;
164+
}
165+
160166
public JsonSchemaFactory build() {
161167
// create builtin keywords with (custom) formats.
162168
return new JsonSchemaFactory(
@@ -169,7 +175,8 @@ public JsonSchemaFactory build() {
169175
jsonMetaSchemas,
170176
uriMap,
171177
forceHttps,
172-
removeEmptyFragmentSuffix
178+
removeEmptyFragmentSuffix,
179+
enableUriSchemaCache
173180
);
174181
}
175182
}
@@ -185,6 +192,7 @@ public JsonSchemaFactory build() {
185192
private final ConcurrentMap<URI, JsonSchema> uriSchemaCache = new ConcurrentHashMap<URI, JsonSchema>();
186193
private final boolean forceHttps;
187194
private final boolean removeEmptyFragmentSuffix;
195+
private final boolean enableUriSchemaCache;
188196

189197

190198
private JsonSchemaFactory(
@@ -197,7 +205,8 @@ private JsonSchemaFactory(
197205
final Map<String, JsonMetaSchema> jsonMetaSchemas,
198206
final Map<String, String> uriMap,
199207
final boolean forceHttps,
200-
final boolean removeEmptyFragmentSuffix) {
208+
final boolean removeEmptyFragmentSuffix,
209+
final boolean enableUriSchemaCache) {
201210
if (jsonMapper == null) {
202211
throw new IllegalArgumentException("ObjectMapper must not be null");
203212
} else if (yamlMapper == null) {
@@ -225,6 +234,7 @@ private JsonSchemaFactory(
225234
this.uriMap = uriMap;
226235
this.forceHttps = forceHttps;
227236
this.removeEmptyFragmentSuffix = removeEmptyFragmentSuffix;
237+
this.enableUriSchemaCache = enableUriSchemaCache;
228238
}
229239

230240
/**
@@ -373,7 +383,7 @@ public JsonSchema getSchema(final URI schemaUri, final SchemaValidatorsConfig co
373383
throw new JsonSchemaException(e);
374384
}
375385

376-
if (uriSchemaCache.containsKey(mappedUri)) {
386+
if (enableUriSchemaCache && uriSchemaCache.containsKey(mappedUri)) {
377387
JsonSchema cachedUriSchema = uriSchemaCache.get(mappedUri);
378388
// This is important because if we use same JsonSchemaFactory for creating multiple JSONSchema instances,
379389
// these schemas will be cached along with config. We have to replace the config for cached $ref references
@@ -404,7 +414,10 @@ public JsonSchema getSchema(final URI schemaUri, final SchemaValidatorsConfig co
404414
validationContext.setConfig(config);
405415
jsonSchema = new JsonSchema(validationContext, mappedUri, schemaNode);
406416
}
407-
uriSchemaCache.put(mappedUri, jsonSchema);
417+
418+
if (enableUriSchemaCache) {
419+
uriSchemaCache.put(mappedUri, jsonSchema);
420+
}
408421

409422
return jsonSchema;
410423
} finally {
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package com.networknt.schema;
2+
3+
import com.fasterxml.jackson.core.JsonProcessingException;
4+
import com.fasterxml.jackson.databind.ObjectMapper;
5+
import com.networknt.schema.uri.ClasspathURLFactory;
6+
import com.networknt.schema.uri.URIFetcher;
7+
import com.networknt.schema.uri.URLFactory;
8+
import org.junit.jupiter.api.Test;
9+
10+
import java.io.ByteArrayInputStream;
11+
import java.io.IOException;
12+
import java.io.InputStream;
13+
import java.net.URI;
14+
import java.nio.charset.StandardCharsets;
15+
import java.util.HashMap;
16+
import java.util.Map;
17+
18+
import static org.junit.jupiter.api.Assertions.assertEquals;
19+
20+
public class JsonSchemaFactoryUriCacheTest {
21+
22+
private final ObjectMapper objectMapper = new ObjectMapper();
23+
private final ClasspathURLFactory classpathURLFactory = new ClasspathURLFactory();
24+
25+
@Test
26+
public void cacheEnabled() throws JsonProcessingException {
27+
runCacheTest(true);
28+
}
29+
30+
@Test
31+
public void cacheDisabled() throws JsonProcessingException {
32+
runCacheTest(false);
33+
}
34+
35+
private void runCacheTest(boolean enableCache) throws JsonProcessingException {
36+
CustomURIFetcher fetcher = new CustomURIFetcher();
37+
JsonSchemaFactory factory = buildJsonSchemaFactory(fetcher, enableCache);
38+
URI schemaUri = classpathURLFactory.create("cache:uri_mapping/schema1.json");
39+
String schema = "{ \"$schema\": \"https://json-schema.org/draft/2020-12/schema#\", \"title\": \"json-object-with-schema\", \"type\": \"string\" }";
40+
fetcher.addResource(schemaUri, schema);
41+
assertEquals(objectMapper.readTree(schema), factory.getSchema(schemaUri, new SchemaValidatorsConfig()).schemaNode);
42+
43+
String modifiedSchema = "{ \"$schema\": \"https://json-schema.org/draft/2020-12/schema#\", \"title\": \"json-object-with-schema\", \"type\": \"object\" }";
44+
fetcher.addResource(schemaUri, modifiedSchema);
45+
46+
assertEquals(objectMapper.readTree(enableCache ? schema : modifiedSchema), factory.getSchema(schemaUri, new SchemaValidatorsConfig()).schemaNode);
47+
}
48+
49+
private JsonSchemaFactory buildJsonSchemaFactory(CustomURIFetcher uriFetcher, boolean enableUriSchemaCache) {
50+
return JsonSchemaFactory.builder(JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V202012))
51+
.enableUriSchemaCache(enableUriSchemaCache)
52+
.uriFetcher(uriFetcher, "cache")
53+
.uriFactory(new URLFactory(), "cache")
54+
.addMetaSchema(JsonMetaSchema.getV202012())
55+
.build();
56+
}
57+
58+
private class CustomURIFetcher implements URIFetcher {
59+
60+
private Map<URI, InputStream> uriToResource = new HashMap<>();
61+
62+
void addResource(URI uri, String schema) {
63+
addResource(uri, new ByteArrayInputStream(schema.getBytes(StandardCharsets.UTF_8)));
64+
}
65+
66+
void addResource(URI uri, InputStream is) {
67+
uriToResource.put(uri, is);
68+
}
69+
70+
@Override
71+
public InputStream fetch(URI uri) throws IOException {
72+
return uriToResource.get(uri);
73+
}
74+
}
75+
}

0 commit comments

Comments
 (0)