Skip to content

Commit b5e962d

Browse files
authored
Merge pull request #306 from Subhajitdas298/master
Added schema version detection with schema tag
2 parents fc24edd + 2fa85e6 commit b5e962d

File tree

11 files changed

+212
-91
lines changed

11 files changed

+212
-91
lines changed
Lines changed: 45 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,45 @@
1-
/*
2-
* Copyright (c) 2016 Network New Technologies Inc.
3-
*
4-
* Licensed under the Apache License, Version 2.0 (the "License");
5-
* you may not use this file except in compliance with the License.
6-
* You may obtain a copy of the License at
7-
*
8-
* http://www.apache.org/licenses/LICENSE-2.0
9-
*
10-
* Unless required by applicable law or agreed to in writing, software
11-
* distributed under the License is distributed on an "AS IS" BASIS,
12-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13-
* See the License for the specific language governing permissions and
14-
* limitations under the License.
15-
*/
16-
17-
package com.networknt.schema;
18-
19-
import java.util.Collections;
20-
import java.util.Set;
21-
22-
public class JsonSchemaException extends RuntimeException {
23-
private static final long serialVersionUID = -7805792737596582110L;
24-
private ValidationMessage validationMessage;
25-
26-
public JsonSchemaException(ValidationMessage validationMessage) {
27-
super(validationMessage.getMessage());
28-
this.validationMessage = validationMessage;
29-
}
30-
31-
public JsonSchemaException(String message) {
32-
super(message);
33-
}
34-
35-
public JsonSchemaException(Throwable throwable) {
36-
super(throwable);
37-
}
38-
39-
public Set<ValidationMessage> getValidationMessages() {
40-
if (validationMessage == null) {
41-
return Collections.emptySet();
42-
}
43-
return Collections.singleton(validationMessage);
44-
}
45-
}
1+
/*
2+
* Copyright (c) 2016 Network New Technologies Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.networknt.schema;
18+
19+
import java.util.Collections;
20+
import java.util.Set;
21+
22+
public class JsonSchemaException extends RuntimeException {
23+
private static final long serialVersionUID = -7805792737596582110L;
24+
private ValidationMessage validationMessage;
25+
26+
public JsonSchemaException(ValidationMessage validationMessage) {
27+
super(validationMessage.getMessage());
28+
this.validationMessage = validationMessage;
29+
}
30+
31+
public JsonSchemaException(String message) {
32+
super(message);
33+
}
34+
35+
public JsonSchemaException(Throwable throwable) {
36+
super(throwable);
37+
}
38+
39+
public Set<ValidationMessage> getValidationMessages() {
40+
if (validationMessage == null) {
41+
return Collections.emptySet();
42+
}
43+
return Collections.singleton(validationMessage);
44+
}
45+
}

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

Lines changed: 27 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,8 @@
2525

2626
import java.io.IOException;
2727
import java.io.InputStream;
28-
import java.net.MalformedURLException;
2928
import java.net.URI;
3029
import java.net.URISyntaxException;
31-
import java.net.URL;
3230
import java.util.Collection;
3331
import java.util.HashMap;
3432
import java.util.Map;
@@ -165,23 +163,17 @@ private JsonSchemaFactory(
165163
final Map<String, String> uriMap) {
166164
if (mapper == null) {
167165
throw new IllegalArgumentException("ObjectMapper must not be null");
168-
}
169-
if (defaultMetaSchemaURI == null || defaultMetaSchemaURI.trim().isEmpty()) {
166+
} else if (defaultMetaSchemaURI == null || defaultMetaSchemaURI.trim().isEmpty()) {
170167
throw new IllegalArgumentException("defaultMetaSchemaURI must not be null or empty");
171-
}
172-
if (uriFactory == null) {
168+
} else if (uriFactory == null) {
173169
throw new IllegalArgumentException("URIFactory must not be null");
174-
}
175-
if (uriFetcher == null) {
170+
} else if (uriFetcher == null) {
176171
throw new IllegalArgumentException("URIFetcher must not be null");
177-
}
178-
if (jsonMetaSchemas == null || jsonMetaSchemas.isEmpty()) {
172+
} else if (jsonMetaSchemas == null || jsonMetaSchemas.isEmpty()) {
179173
throw new IllegalArgumentException("Json Meta Schemas must not be null or empty");
180-
}
181-
if (jsonMetaSchemas.get(defaultMetaSchemaURI) == null) {
174+
} else if (jsonMetaSchemas.get(defaultMetaSchemaURI) == null) {
182175
throw new IllegalArgumentException("Meta Schema for default Meta Schema URI must be provided");
183-
}
184-
if (uriMap == null) {
176+
} else if (uriMap == null) {
185177
throw new IllegalArgumentException("URL Mappings must not be null");
186178
}
187179
this.mapper = mapper;
@@ -219,32 +211,25 @@ public static JsonSchemaFactory getInstance() {
219211
}
220212

221213
public static JsonSchemaFactory getInstance(SpecVersion.VersionFlag versionFlag) {
222-
if (versionFlag == SpecVersion.VersionFlag.V201909) {
223-
JsonMetaSchema v201909 = JsonMetaSchema.getV201909();
224-
return builder()
225-
.defaultMetaSchemaURI(v201909.getUri())
226-
.addMetaSchema(v201909)
227-
.build();
228-
} else if (versionFlag == SpecVersion.VersionFlag.V7) {
229-
JsonMetaSchema v7 = JsonMetaSchema.getV7();
230-
return builder()
231-
.defaultMetaSchemaURI(v7.getUri())
232-
.addMetaSchema(v7)
233-
.build();
234-
} else if (versionFlag == SpecVersion.VersionFlag.V6) {
235-
JsonMetaSchema v6 = JsonMetaSchema.getV6();
236-
return builder()
237-
.defaultMetaSchemaURI(v6.getUri())
238-
.addMetaSchema(v6)
239-
.build();
240-
} else if (versionFlag == SpecVersion.VersionFlag.V4) {
241-
JsonMetaSchema v4 = JsonMetaSchema.getV4();
242-
return builder()
243-
.defaultMetaSchemaURI(v4.getUri())
244-
.addMetaSchema(v4)
245-
.build();
214+
JsonMetaSchema metaSchema = null;
215+
switch (versionFlag) {
216+
case V201909:
217+
metaSchema = JsonMetaSchema.getV201909();
218+
break;
219+
case V7:
220+
metaSchema = JsonMetaSchema.getV7();
221+
break;
222+
case V6:
223+
metaSchema = JsonMetaSchema.getV6();
224+
break;
225+
case V4:
226+
metaSchema = JsonMetaSchema.getV4();
227+
break;
246228
}
247-
return null;
229+
return builder()
230+
.defaultMetaSchemaURI(metaSchema.getUri())
231+
.addMetaSchema(metaSchema)
232+
.build();
248233
}
249234

250235
public static Builder builder(final JsonSchemaFactory blueprint) {
@@ -266,9 +251,7 @@ public static Builder builder(final JsonSchemaFactory blueprint) {
266251
protected JsonSchema newJsonSchema(final URI schemaUri, final JsonNode schemaNode, final SchemaValidatorsConfig config) {
267252
final ValidationContext validationContext = createValidationContext(schemaNode);
268253
validationContext.setConfig(config);
269-
JsonSchema jsonSchema = new JsonSchema(validationContext, schemaUri, schemaNode)
270-
.initialize();
271-
return jsonSchema;
254+
return new JsonSchema(validationContext, schemaUri, schemaNode).initialize();
272255
}
273256

274257
protected ValidationContext createValidationContext(final JsonNode schemaNode) {
@@ -281,7 +264,7 @@ private JsonMetaSchema findMetaSchemaForSchema(final JsonNode schemaNode) {
281264
final String uri = uriNode == null || uriNode.isNull() ? defaultMetaSchemaURI : normalizeMetaSchemaUri(uriNode.textValue());
282265
final JsonMetaSchema jsonMetaSchema = jsonMetaSchemas.get(uri);
283266
if (jsonMetaSchema == null) {
284-
throw new JsonSchemaException("Unknown Metaschema: " + uri);
267+
throw new JsonSchemaException("Unknown MetaSchema: " + uri);
285268
}
286269
return jsonMetaSchema;
287270
}
@@ -324,7 +307,7 @@ public JsonSchema getSchema(final InputStream schemaStream) {
324307
public JsonSchema getSchema(final URI schemaUri, final SchemaValidatorsConfig config) {
325308
try {
326309
InputStream inputStream = null;
327-
final Map<String, String> map = (config != null) ? config.getUriMappings() : new HashMap<String, String>(uriMap);
310+
final Map<String, String> map = (config != null) ? config.getUriMappings() : new HashMap<String, String>();
328311
map.putAll(uriMap);
329312

330313
final URI mappedUri;
@@ -388,7 +371,6 @@ public JsonSchema getSchema(final JsonNode jsonNode) {
388371
}
389372

390373
private boolean idMatchesSourceUri(final JsonMetaSchema metaSchema, final JsonNode schema, final URI schemaUri) {
391-
392374
String id = metaSchema.readId(schema);
393375
if (id == null || id.isEmpty()) {
394376
return false;
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Copyright (c) 2016 Network New Technologies Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.networknt.schema;
18+
19+
import com.fasterxml.jackson.databind.JsonNode;
20+
import com.fasterxml.jackson.databind.ObjectMapper;
21+
22+
public class SpecVersionDetector {
23+
24+
private static final String SCHEMA_TAG = "$schema";
25+
26+
private static ObjectMapper mapper = new ObjectMapper();
27+
28+
/**
29+
* Detects schema version based on the schema tag
30+
*
31+
* @param jsonNode Json Node to read from
32+
* @return Spec version
33+
*/
34+
public static SpecVersion.VersionFlag detect(JsonNode jsonNode) {
35+
if (!jsonNode.has(SCHEMA_TAG))
36+
throw new JsonSchemaException("Schema tag not present");
37+
38+
String schemaUri = JsonSchemaFactory.normalizeMetaSchemaUri(jsonNode.get(SCHEMA_TAG).asText());
39+
if (schemaUri.equals(JsonMetaSchema.getV4().getUri()))
40+
return SpecVersion.VersionFlag.V4;
41+
else if (schemaUri.equals(JsonMetaSchema.getV6().getUri()))
42+
return SpecVersion.VersionFlag.V6;
43+
else if (schemaUri.equals(JsonMetaSchema.getV7().getUri()))
44+
return SpecVersion.VersionFlag.V7;
45+
else if (schemaUri.equals(JsonMetaSchema.getV201909().getUri()))
46+
return SpecVersion.VersionFlag.V201909;
47+
else
48+
throw new JsonSchemaException("Unrecognizable schema");
49+
}
50+
51+
}

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010

1111
public class CyclicDependencyTest {
1212

13-
1413
@Test
1514
public void whenDependencyBetweenSchemaThenValidationSuccessful() throws Exception {
1615

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package com.networknt.schema;
2+
3+
import com.fasterxml.jackson.databind.JsonNode;
4+
import com.fasterxml.jackson.databind.ObjectMapper;
5+
import org.junit.Test;
6+
7+
import java.io.IOException;
8+
import java.io.InputStream;
9+
import java.net.URI;
10+
11+
import static org.junit.Assert.*;
12+
13+
public class SpecVersionDetectorTest {
14+
15+
private static final String SCHEMA_TAG_JSON = "schemaTag.json";
16+
17+
private static final ObjectMapper mapper = new ObjectMapper();
18+
19+
@Test
20+
public void detectV4() throws IOException {
21+
InputStream in = Thread.currentThread().getContextClassLoader()
22+
.getResourceAsStream("draft4/" + SCHEMA_TAG_JSON);
23+
JsonNode node = mapper.readTree(in);
24+
SpecVersion.VersionFlag flag = SpecVersionDetector.detect(node);
25+
assertEquals(SpecVersion.VersionFlag.V4, flag);
26+
}
27+
28+
@Test
29+
public void detectV6() throws IOException {
30+
InputStream in = Thread.currentThread().getContextClassLoader()
31+
.getResourceAsStream("draft6/" + SCHEMA_TAG_JSON);
32+
JsonNode node = mapper.readTree(in);
33+
SpecVersion.VersionFlag flag = SpecVersionDetector.detect(node);
34+
assertEquals(SpecVersion.VersionFlag.V6, flag);
35+
}
36+
37+
@Test
38+
public void detectV7() throws IOException {
39+
InputStream in = Thread.currentThread().getContextClassLoader()
40+
.getResourceAsStream("draft7/" + SCHEMA_TAG_JSON);
41+
JsonNode node = mapper.readTree(in);
42+
SpecVersion.VersionFlag flag = SpecVersionDetector.detect(node);
43+
assertEquals(SpecVersion.VersionFlag.V7, flag);
44+
}
45+
46+
@Test
47+
public void detectV201909() throws IOException {
48+
InputStream in = Thread.currentThread().getContextClassLoader()
49+
.getResourceAsStream("draft2019-09/" + SCHEMA_TAG_JSON);
50+
JsonNode node = mapper.readTree(in);
51+
SpecVersion.VersionFlag flag = SpecVersionDetector.detect(node);
52+
assertEquals(SpecVersion.VersionFlag.V201909, flag);
53+
}
54+
55+
@Test(expected = JsonSchemaException.class)
56+
public void detectUnsupportedSchemaVersion() throws IOException {
57+
InputStream in = Thread.currentThread().getContextClassLoader()
58+
.getResourceAsStream("data/" + SCHEMA_TAG_JSON);
59+
JsonNode node = mapper.readTree(in);
60+
SpecVersion.VersionFlag flag = SpecVersionDetector.detect(node);
61+
}
62+
63+
@Test(expected = JsonSchemaException.class)
64+
public void detectMissingSchemaVersion() throws IOException {
65+
InputStream in = Thread.currentThread().getContextClassLoader()
66+
.getResourceAsStream("data/" + "schemaTagMissing.json");
67+
JsonNode node = mapper.readTree(in);
68+
SpecVersion.VersionFlag flag = SpecVersionDetector.detect(node);
69+
}
70+
71+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-03/schema#"
3+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"description": "Test"
3+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"$schema": "https://json-schema.org/draft/2019-09/schema"
3+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-04/schema#"
3+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-06/schema#"
3+
}

0 commit comments

Comments
 (0)