diff --git a/spring-boot/src/main/java/org/springframework/boot/bind/RelaxedDataBinder.java b/spring-boot/src/main/java/org/springframework/boot/bind/RelaxedDataBinder.java index db4afff4a8..60425e5fa3 100644 --- a/spring-boot/src/main/java/org/springframework/boot/bind/RelaxedDataBinder.java +++ b/spring-boot/src/main/java/org/springframework/boot/bind/RelaxedDataBinder.java @@ -451,27 +451,40 @@ public class RelaxedDataBinder extends DataBinder { private List splitPath(String path) { List nodes = new ArrayList(); - 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 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 revised = new ArrayList(); for (int i = 0; i < index; i++) { diff --git a/spring-boot/src/test/java/org/springframework/boot/bind/RelaxedDataBinderTests.java b/spring-boot/src/test/java/org/springframework/boot/bind/RelaxedDataBinderTests.java index 8a9d0f578d..f0c05c9aab 100644 --- a/spring-boot/src/test/java/org/springframework/boot/bind/RelaxedDataBinderTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/bind/RelaxedDataBinderTests.java @@ -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 {