Refine missing field detection logic for paths with multiple arrays

Previously, missing field detection worked correctly for paths
containing a single array, but if the path contained multiple arrays
the extracted value would be a list containing a single empty list.
In this case the field would not be considered missing when, in fact
it should have been.

This commit updates the missing field detection logic to recursively
examine the extracted value and, when it's a collection, the values
that it contains. As a result, a field will be considered to be
missing if it isn't present, if it's an empty collection, or if it's
a collection that only contains empty collections or, to any depth,
collections of empty collections.

Closes gh-519
This commit is contained in:
Andy Wilkinson
2018-07-19 11:11:38 +01:00
parent 001fb388b0
commit 81b55d470b
2 changed files with 39 additions and 3 deletions

View File

@@ -86,8 +86,23 @@ class JsonContentHandler implements ContentHandler {
}
ExtractedField extracted = this.fieldProcessor.extract(candidate.getPath(),
payload);
return extracted.getValue() instanceof Collection
&& ((Collection<?>) extracted.getValue()).isEmpty();
return isEmptyCollection(extracted.getValue());
}
private boolean isEmptyCollection(Object value) {
if (!(value instanceof Collection)) {
return false;
}
Collection<?> collection = (Collection<?>) value;
if (collection.isEmpty()) {
return true;
}
for (Object entry : collection) {
if (!isEmptyCollection(entry)) {
return false;
}
}
return true;
}
@Override

View File

@@ -158,7 +158,7 @@ public class JsonContentHandlerTests {
}
@Test
public void describedFieldThatIsSometimesPresentChildOfOptionalArrayIsNotConsideredMissing() {
public void describedSometimesPresentFieldThatIsChildOfSometimesPresentOptionalArrayIsNotConsideredMissing() {
List<FieldDescriptor> missingFields = new JsonContentHandler(
"{\"a\":[ {\"b\": \"bravo\"}, {\"b\": \"bravo\", \"c\": { \"d\": \"delta\"}}]}"
.getBytes()).findMissingFields(
@@ -167,4 +167,25 @@ public class JsonContentHandlerTests {
assertThat(missingFields.size(), is(equalTo(0)));
}
@Test
public void describedMissingFieldThatIsChildOfNestedOptionalArrayThatIsEmptyIsNotConsideredMissing() {
List<FieldDescriptor> missingFields = new JsonContentHandler(
"{\"a\":[{\"b\":[]}]}".getBytes()).findMissingFields(
Arrays.asList(new FieldDescriptor("a.[].b").optional(),
new FieldDescriptor("a.[].b.[]").optional(),
new FieldDescriptor("a.[].b.[].c")));
assertThat(missingFields.size(), is(equalTo(0)));
}
@Test
public void describedMissingFieldThatIsChildOfNestedOptionalArrayThatContainsAnObjectIsConsideredMissing() {
List<FieldDescriptor> missingFields = new JsonContentHandler(
"{\"a\":[{\"b\":[{}]}]}".getBytes()).findMissingFields(
Arrays.asList(new FieldDescriptor("a.[].b").optional(),
new FieldDescriptor("a.[].b.[]").optional(),
new FieldDescriptor("a.[].b.[].c")));
assertThat(missingFields.size(), is(equalTo(1)));
assertThat(missingFields.get(0).getPath(), is(equalTo("a.[].b.[].c")));
}
}