Polish JSON field path bracket notation contribution

Closes gh-131
This commit is contained in:
Andy Wilkinson
2015-09-22 16:58:51 +01:00
parent f3b83f977e
commit 42aa996277
3 changed files with 40 additions and 24 deletions

View File

@@ -92,10 +92,14 @@ must be compatible with `application/xml`.
[[documenting-your-api-request-response-payloads-json-field-paths]]
===== JSON field paths
JSON field paths use `.` or bracket notation to descend into a child object and `[]` to
identify an array. Using bracket notation enables the use of `.` within a key name.
JSON field paths use either dot notation or bracket notation. Dot notation uses '.' to
separate each key in the path; `a.b`, for example. Bracket notation wraps each key in
square brackets and single quotes; `['a']['b']`, for example. In either case, `[]` is used
to identify an array. Dot notation is more concise, but using bracket notation enables the
use of `.` within a key name; `['a.b']`, for example. The two different notations can be
used in the same path; `a['b']`, for example.
For example, with this JSON payload:
With this JSON payload:
[source,json,indent=0]
----

View File

@@ -33,7 +33,6 @@ final class JsonFieldPath {
private static final Pattern BRACKETS_AND_ARRAY_PATTERN = Pattern
.compile("\\[\'(.+?)\'\\]|\\[([0-9]+|\\*){0,1}\\]");
private static final Pattern ARRAY_INDEX_PATTERN = Pattern
.compile("\\[([0-9]+|\\*){0,1}\\]");
@@ -85,34 +84,35 @@ final class JsonFieldPath {
int previous = 0;
List<String> tokens = new ArrayList<>();
List<String> segments = new ArrayList<>();
while (matcher.find()) {
if (previous != matcher.start()) {
tokens.addAll(expandToken(path.substring(previous, matcher.start())));
segments.addAll(extractDotSeparatedSegments(path.substring(previous,
matcher.start())));
}
if (matcher.group(1) != null) {
tokens.add(matcher.group(1));
} else {
tokens.add(matcher.group());
segments.add(matcher.group(1));
}
else {
segments.add(matcher.group());
}
previous = matcher.end(0);
}
if (previous < path.length()) {
tokens.addAll(expandToken(path.substring(previous)));
segments.addAll(extractDotSeparatedSegments(path.substring(previous)));
}
return tokens;
return segments;
}
private static List<String> expandToken(String token) {
String[] tokens = token.split("\\.");
List<String> expandedTokens = new ArrayList<>();
for (String aToken : tokens) {
if (aToken.length() > 0) {
expandedTokens.add(aToken);
private static List<String> extractDotSeparatedSegments(String path) {
List<String> segments = new ArrayList<>();
for (String segment : path.split("\\.")) {
if (segment.length() > 0) {
segments.add(segment);
}
}
return expandedTokens;
return segments;
}
}

View File

@@ -111,7 +111,8 @@ public class JsonFieldProcessorTests {
List<List<Map<String, String>>> alpha = Arrays.asList(
Arrays.asList(entry1, entry2), Arrays.asList(entry3));
payload.put("a", alpha);
assertThat(this.fieldProcessor.extract(JsonFieldPath.compile("a[][].id"), payload),
assertThat(
this.fieldProcessor.extract(JsonFieldPath.compile("a[][].id"), payload),
equalTo((Object) Arrays.asList("1", "2", "3")));
}
@@ -124,15 +125,15 @@ public class JsonFieldProcessorTests {
List<List<Map<String, Object>>> alpha = Arrays.asList(
Arrays.asList(entry1, entry2), Arrays.asList(entry3));
payload.put("a", alpha);
assertThat(this.fieldProcessor.extract(JsonFieldPath.compile("a[][].ids"), payload),
equalTo((Object) Arrays.asList(Arrays.asList(1, 2), Arrays.asList(3),
Arrays.asList(4))));
assertThat(this.fieldProcessor.extract(JsonFieldPath.compile("a[][].ids"),
payload), equalTo((Object) Arrays.asList(Arrays.asList(1, 2),
Arrays.asList(3), Arrays.asList(4))));
}
@Test(expected = FieldDoesNotExistException.class)
public void nonExistentTopLevelField() {
this.fieldProcessor
.extract(JsonFieldPath.compile("a"), new HashMap<String, Object>());
this.fieldProcessor.extract(JsonFieldPath.compile("a"),
new HashMap<String, Object>());
}
@Test(expected = FieldDoesNotExistException.class)
@@ -216,6 +217,17 @@ public class JsonFieldProcessorTests {
assertThat(payload.size(), equalTo(0));
}
@Test
public void extractNestedEntryWithDotInKeys() throws IOException {
Map<String, Object> payload = new HashMap<>();
Map<String, Object> alpha = new HashMap<>();
payload.put("a.key", alpha);
alpha.put("b.key", "bravo");
assertThat(this.fieldProcessor.extract(
JsonFieldPath.compile("['a.key']['b.key']"), payload),
equalTo((Object) "bravo"));
}
private Map<String, String> createEntry(String... pairs) {
Map<String, String> entry = new HashMap<>();
for (String pair : pairs) {