Fix JSON field type resolution for top-level and nested array fields

Previously, the logic that determined the field’s type would incorrectly
look at the contents of the array. For example, if the array contained
one or more objects, the field’s type would be resolved as Object rather
than Array.

This commit updates JsonFieldPath to record when a path explicitly
identifies an array so that the array itself is used to determine the
field’s type rather than its contents.

Closes gh-292
This commit is contained in:
Andy Wilkinson
2016-08-24 12:29:14 +01:00
parent 4e4d01a459
commit 0f1f84e6a6
8 changed files with 91 additions and 34 deletions

View File

@@ -17,6 +17,7 @@
package org.springframework.restdocs.payload;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -42,16 +43,24 @@ final class JsonFieldPath {
private final boolean precise;
private JsonFieldPath(String rawPath, List<String> segments, boolean precise) {
private final boolean array;
private JsonFieldPath(String rawPath, List<String> segments, boolean precise,
boolean array) {
this.rawPath = rawPath;
this.segments = segments;
this.precise = precise;
this.array = array;
}
boolean isPrecise() {
return this.precise;
}
boolean isArray() {
return this.array;
}
List<String> getSegments() {
return this.segments;
}
@@ -63,7 +72,8 @@ final class JsonFieldPath {
static JsonFieldPath compile(String path) {
List<String> segments = extractSegments(path);
return new JsonFieldPath(path, segments, matchesSingleValue(segments));
return new JsonFieldPath(path, segments, matchesSingleValue(segments),
isArraySegment(segments.get(segments.size() - 1)));
}
static boolean isArraySegment(String segment) {
@@ -71,8 +81,9 @@ final class JsonFieldPath {
}
static boolean matchesSingleValue(List<String> segments) {
for (String segment : segments) {
if (isArraySegment(segment)) {
Iterator<String> iterator = segments.iterator();
while (iterator.hasNext()) {
if (isArraySegment(iterator.next()) && iterator.hasNext()) {
return false;
}
}

View File

@@ -57,7 +57,7 @@ final class JsonFieldProcessor {
if (matches.isEmpty()) {
throw new FieldDoesNotExistException(path);
}
if (path.isPrecise()) {
if ((!path.isArray()) && path.isPrecise()) {
return matches.get(0);
}
else {

View File

@@ -44,7 +44,7 @@ class JsonFieldTypeResolver {
}
return commonType;
}
return determineFieldType(this.fieldProcessor.extract(fieldPath, payload));
return determineFieldType(field);
}
private JsonFieldType determineFieldType(Object fieldValue) {