Re-write of path parsing pieces of RelaxedDataBinder

Keys with explicit indexes (e.g. foo[bar]) were handled only
partially before this change and in quite a crude way. The main
new feature (or fixed bug if you prefer) is that map keys with
periods were not identified correctly, so foo[bar.spam] came out
wrong. By scanning the key for indexes "[]" first, we can split
the logic better to make sure that all keys can be explicitly
indexed if desired. I believe this would work in YAML as well
but it definitely works for properties file inputs.

Fixes gh-2387 (I believe)
pull/2809/head
Dave Syer 10 years ago
parent 44a708ea5c
commit ff637d3aaa

@ -451,27 +451,40 @@ public class RelaxedDataBinder extends DataBinder {
private List<PathNode> splitPath(String path) {
List<PathNode> nodes = new ArrayList<PathNode>();
for (String name : StringUtils.delimitedListToStringArray(path, ".")) {
for (String sub : StringUtils.delimitedListToStringArray(name, "[")) {
if (StringUtils.hasText(sub)) {
if (sub.endsWith("]")) {
sub = sub.substring(0, sub.length() - 1);
if (sub.matches("[0-9]+")) {
nodes.add(new ArrayIndexNode(sub));
}
else {
nodes.add(new MapIndexNode(sub));
}
}
else {
nodes.add(new PropertyNode(sub));
}
}
String current = extractIndexedPaths(path, nodes);
for (String name : StringUtils.delimitedListToStringArray(current, ".")) {
if (StringUtils.hasText(name)) {
nodes.add(new PropertyNode(name));
}
}
return nodes;
}
private String extractIndexedPaths(String path, List<PathNode> nodes) {
int begin = 0;
int startRef = path.indexOf("[");
String current = path;
while (startRef >= 0) {
if (startRef > begin) {
nodes.addAll(splitPath(current.substring(begin, startRef)));
}
int endRef = current.indexOf("]", startRef);
if (endRef > 0) {
String sub = current.substring(startRef + 1, endRef);
if (sub.matches("[0-9]+")) {
nodes.add(new ArrayIndexNode(sub));
}
else {
nodes.add(new MapIndexNode(sub));
}
}
begin = endRef + 1;
current = current.substring(begin);
startRef = current.indexOf("[");
}
return current;
}
public void collapseKeys(int index) {
List<PathNode> revised = new ArrayList<PathNode>();
for (int i = 0; i < index; i++) {

@ -301,6 +301,14 @@ public class RelaxedDataBinderTests {
assertEquals("123", target.getNested().get("value.foo"));
}
@Test
public void testBindNestedMapOfStringReferenced() throws Exception {
TargetWithNestedMapOfString target = new TargetWithNestedMapOfString();
bind(target, "nested.foo: bar\n" + "nested[value.foo]: 123");
assertEquals("bar", target.getNested().get("foo"));
assertEquals("123", target.getNested().get("value.foo"));
}
@Test
public void testBindNestedMapOfEnum() throws Exception {
this.conversionService = new DefaultConversionService();
@ -317,6 +325,13 @@ public class RelaxedDataBinderTests {
assertEquals("123", target.getNested().get("value"));
}
@Test
public void testBindNestedMapBracketReferencedAndPeriods() throws Exception {
TargetWithNestedMap target = new TargetWithNestedMap();
bind(target, "nested[foo]: bar\n" + "nested[foo.value]: 123");
assertEquals("123", target.getNested().get("foo.value"));
}
@SuppressWarnings("unchecked")
@Test
public void testBindDoubleNestedMap() throws Exception {

Loading…
Cancel
Save