From 2066c04a3e9c48a93db097b33a5f84bca32a333d Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 8 Jan 2014 09:37:51 +0000 Subject: [PATCH] Make Map a special case in RelaxedDataBinder Fixes gh-195 --- .../boot/bind/RelaxedDataBinder.java | 24 +++++++++++++++++++ .../boot/bind/RelaxedDataBinderTests.java | 20 ++++++++++++++++ .../EnableConfigurationPropertiesTests.java | 2 -- 3 files changed, 44 insertions(+), 2 deletions(-) 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 e563dbabaf..51244a5dc9 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 @@ -187,6 +187,14 @@ public class RelaxedDataBinder extends DataBinder { if (descriptor == null || descriptor.isMap()) { if (descriptor != null) { wrapper.getPropertyValue(name + "[foo]"); + TypeDescriptor valueDescriptor = descriptor.getMapValueTypeDescriptor(); + if (valueDescriptor != null) { + Class valueType = valueDescriptor.getObjectType(); + if (valueType != null + && CharSequence.class.isAssignableFrom(valueType)) { + path.collapseKeys(index); + } + } } path.mapIndex(index); extendMapIfNecessary(wrapper, path, index); @@ -278,6 +286,22 @@ public class RelaxedDataBinder extends DataBinder { this.nodes = splitPath(path); } + public void collapseKeys(int index) { + List revised = new ArrayList(); + for (int i = 0; i < index; i++) { + revised.add(this.nodes.get(i)); + } + StringBuilder builder = new StringBuilder(); + for (int i = index; i < this.nodes.size(); i++) { + if (i > index) { + builder.append("."); + } + builder.append(this.nodes.get(i).name); + } + revised.add(new PropertyNode(builder.toString())); + this.nodes = revised; + } + public void mapIndex(int index) { PathNode node = this.nodes.get(index); if (node instanceof PropertyNode) { 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 39d125948b..279c997a86 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 @@ -250,6 +250,14 @@ public class RelaxedDataBinderTests { assertEquals("123", target.getNested().get("value")); } + @Test + public void testBindNestedMapOfString() 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 testBindNestedMapBracketReferenced() throws Exception { TargetWithNestedMap target = new TargetWithNestedMap(); @@ -469,6 +477,18 @@ public class RelaxedDataBinderTests { } } + public static class TargetWithNestedMapOfString { + private Map nested; + + public Map getNested() { + return this.nested; + } + + public void setNested(Map nested) { + this.nested = nested; + } + } + public static class TargetWithNestedMapOfListOfString { private Map> nested; diff --git a/spring-boot/src/test/java/org/springframework/boot/context/properties/EnableConfigurationPropertiesTests.java b/spring-boot/src/test/java/org/springframework/boot/context/properties/EnableConfigurationPropertiesTests.java index 47851a1c18..cf0500c1a3 100644 --- a/spring-boot/src/test/java/org/springframework/boot/context/properties/EnableConfigurationPropertiesTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/context/properties/EnableConfigurationPropertiesTests.java @@ -26,7 +26,6 @@ import javax.validation.constraints.NotNull; import org.hamcrest.Matchers; import org.junit.After; -import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -326,7 +325,6 @@ public class EnableConfigurationPropertiesTests { } @Test - @Ignore("This is challenging, so maybe not supportable?") public void testBindingWithMapKeyWithPeriod() { this.context.register(ResourceBindingPropertiesWithMap.class); this.context.refresh();