Skip to content

Commit 711e5bb

Browse files
committed
changing ObjectSchema#definesProperty() implementation to recursively handle pattern properties
1 parent 48a1966 commit 711e5bb

File tree

4 files changed

+75
-17
lines changed

4 files changed

+75
-17
lines changed

core/src/main/java/org/everit/json/schema/ObjectSchema.java

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,6 @@
3232

3333
import org.json.JSONObject;
3434

35-
import com.google.common.base.Splitter;
36-
import com.google.common.collect.Lists;
37-
3835
/**
3936
* Object schema validator.
4037
*/
@@ -398,30 +395,39 @@ public void validate(final Object subject) {
398395
@Override
399396
public boolean definesProperty(String field) {
400397
field = field.replaceFirst("^#", "").replaceFirst("^/", "");
401-
return !field.isEmpty() && (definesPatternProperty(field)
402-
|| definesSchemaDependencyProperty(field)
403-
|| definesSchemaProperty(field));
398+
int firstSlashIdx = field.indexOf('/');
399+
String nextToken, remaining;
400+
if (firstSlashIdx == -1) {
401+
nextToken = field;
402+
remaining = null;
403+
} else {
404+
nextToken = field.substring(0, firstSlashIdx);
405+
remaining = field.substring(firstSlashIdx + 1);
406+
}
407+
return !field.isEmpty() && (definesSchemaProperty(nextToken, remaining)
408+
|| definesPatternProperty(nextToken, remaining)
409+
|| definesSchemaDependencyProperty(field));
404410
}
405411

406-
private boolean definesSchemaProperty(final String field) {
407-
List<String> fields = Lists.newArrayList(Splitter.on("/").limit(2).split(field));
408-
String current = unescape(fields.get(0));
409-
boolean hasSuffix = fields.size() > 1;
412+
private boolean definesSchemaProperty(String current, final String remaining) {
413+
current = unescape(current);
414+
boolean hasSuffix = !(remaining == null);
410415
if (propertySchemas.containsKey(current)) {
411416
if (hasSuffix) {
412-
String suffix = fields.get(1);
413-
return propertySchemas.get(current).definesProperty(suffix);
417+
return propertySchemas.get(current).definesProperty(remaining);
414418
} else {
415419
return true;
416420
}
417421
}
418422
return false;
419423
}
420424

421-
private boolean definesPatternProperty(final String field) {
425+
private boolean definesPatternProperty(final String current, final String remaining) {
422426
return patternProperties.keySet()
423427
.stream()
424-
.filter(pattern -> pattern.matcher(field).matches())
428+
.filter(pattern -> pattern.matcher(current).matches())
429+
.map(pattern -> patternProperties.get(pattern))
430+
.filter(schema -> remaining == null || schema.definesProperty(remaining))
425431
.findAny()
426432
.isPresent();
427433
}

core/src/test/java/org/everit/json/schema/loader/DefinesPropertyTest.java

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*/
1616
package org.everit.json.schema.loader;
1717

18+
import java.io.InputStream;
19+
1820
import org.everit.json.schema.ObjectSchema;
1921
import org.everit.json.schema.Schema;
2022
import org.json.JSONObject;
@@ -23,16 +25,14 @@
2325
import org.junit.BeforeClass;
2426
import org.junit.Test;
2527

26-
import java.io.InputStream;
27-
2828
public class DefinesPropertyTest {
2929

3030
private static JSONObject ALL_SCHEMAS;
3131

3232
@BeforeClass
3333
public static void before() {
3434
InputStream stream = DefinesPropertyTest.class.getResourceAsStream(
35-
"/org/everit/jsonvalidator/testschemas.json");
35+
"/org/everit/jsonvalidator/testschemas.json");
3636
ALL_SCHEMAS = new JSONObject(new JSONTokener(stream));
3737
}
3838

@@ -107,4 +107,22 @@ public void objectEscape() {
107107
Assert.assertFalse(actual.definesProperty("#/a~0b/c/d"));
108108
}
109109

110+
@Test
111+
public void testOfTest() {
112+
ObjectSchema actual = (ObjectSchema) SchemaLoader.load(get("patternPropsAndSchemaDeps"));
113+
JSONObject input = new JSONObject(new JSONTokener(
114+
getClass().getResourceAsStream("/org/everit/jsonvalidator/objecttestcases.json")))
115+
.getJSONObject("validOfPatternPropsAndSchemaDeps");
116+
actual.validate(input);
117+
}
118+
119+
@Test
120+
public void patternPropsAndSchemaDefs() {
121+
ObjectSchema actual = (ObjectSchema) SchemaLoader.load(get("patternPropsAndSchemaDeps"));
122+
// Assert.assertTrue(actual.definesProperty("#/1stLevel"));
123+
// Assert.assertTrue(actual.definesProperty("#/1stLevel/2ndLevel"));
124+
Assert.assertTrue(actual.definesProperty("#/1stLevel/2ndLevel/3rdLev"));
125+
// Assert.assertTrue(actual.definesProperty("#/1stLevel/2ndLevel/3rdLevel/4thLevel"));
126+
}
127+
110128
}

core/src/test/resources/org/everit/jsonvalidator/objecttestcases.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,5 +47,13 @@
4747
"a" : -5,
4848
"b" : "asd"
4949
}
50+
},
51+
"validOfPatternPropsAndSchemaDeps" : {
52+
"1stLevel" : {
53+
"2ndLevel" : {
54+
"3rdLev" : "whatever"
55+
56+
}
57+
}
5058
}
5159
}

core/src/test/resources/org/everit/jsonvalidator/testschemas.json

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,5 +367,31 @@
367367
"properties" : {
368368
"prop" : { "$ref" : "schema.json" }
369369
}
370+
},
371+
"patternPropsAndSchemaDeps": {
372+
"type" : "object",
373+
"properties" : {
374+
"1stLevel" : {
375+
"dependencies" : {
376+
"2ndLevel" : {
377+
"type" : "object",
378+
"additionalProperties":false,
379+
"patternProperties" : {
380+
"2ndL.*l$" : {
381+
"type" : "object",
382+
"properties" : {
383+
"3rdLev" : {
384+
"type" : "string"
385+
}
386+
},
387+
"additionalProperties":false
388+
}
389+
}
390+
}
391+
}
392+
393+
}
394+
},
395+
"additionalProperties" : false
370396
}
371397
}

0 commit comments

Comments
 (0)