Skip to content

Commit f0ed619

Browse files
lineadphilwebb
authored andcommitted
Supported relaxed binding on inner classes
Update RelaxedDataBinder to support relaxed binding to inner classes in the same way as normal configuration objects. e.g. `nested.foo_bar` => `nested.fooBar` Fixes gh-2463 Closes gh- 2479
1 parent a1cbd93 commit f0ed619

File tree

2 files changed

+62
-4
lines changed

2 files changed

+62
-4
lines changed

spring-boot/src/main/java/org/springframework/boot/bind/RelaxedDataBinder.java

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -286,12 +286,38 @@ private void extendMapIfNecessary(BeanWrapper wrapper, BeanPath path, int index)
286286
}
287287

288288
private String getActualPropertyName(BeanWrapper target, String prefix, String name) {
289-
prefix = StringUtils.hasText(prefix) ? prefix + "." : "";
289+
String propertyName = resolvePropertyName(target, prefix, name);
290+
if (propertyName == null) {
291+
propertyName = resolveNestedPropertyName(target, prefix, name);
292+
}
293+
return (propertyName == null ? name : propertyName);
294+
}
295+
296+
private String resolveNestedPropertyName(BeanWrapper target, String prefix,
297+
String name) {
298+
StringBuilder candidate = new StringBuilder();
299+
for (String field : name.split("[_\\-\\.]")) {
300+
candidate.append(candidate.length() > 0 ? "." : "");
301+
candidate.append(field);
302+
String nested = resolvePropertyName(target, prefix, candidate.toString());
303+
if (nested != null) {
304+
String propertyName = resolvePropertyName(target,
305+
joinString(prefix, nested),
306+
name.substring(candidate.length() + 1));
307+
if (propertyName != null) {
308+
return joinString(nested, propertyName);
309+
}
310+
}
311+
}
312+
return null;
313+
}
314+
315+
private String resolvePropertyName(BeanWrapper target, String prefix, String name) {
290316
Iterable<String> names = getNameAndAliases(name);
291317
for (String nameOrAlias : names) {
292318
for (String candidate : new RelaxedNames(nameOrAlias)) {
293319
try {
294-
if (target.getPropertyType(prefix + candidate) != null) {
320+
if (target.getPropertyType(joinString(prefix, candidate)) != null) {
295321
return candidate;
296322
}
297323
}
@@ -300,7 +326,11 @@ private String getActualPropertyName(BeanWrapper target, String prefix, String n
300326
}
301327
}
302328
}
303-
return name;
329+
return null;
330+
}
331+
332+
private String joinString(String prefix, String name) {
333+
return (StringUtils.hasLength(prefix) ? prefix + "." + name : name);
304334
}
305335

306336
private Iterable<String> getNameAndAliases(String name) {

spring-boot/src/test/java/org/springframework/boot/bind/RelaxedDataBinderTests.java

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2014 the original author or authors.
2+
* Copyright 2012-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -201,6 +201,22 @@ public void testBindNested() throws Exception {
201201
assertEquals(123, target.getNested().getValue());
202202
}
203203

204+
@Test
205+
public void testBindRelaxedNestedValue() throws Exception {
206+
TargetWithNestedObject target = new TargetWithNestedObject();
207+
bind(target, "nested_foo_Baz: bar\n" + "nested_value: 123");
208+
assertEquals("bar", target.getNested().getFooBaz());
209+
assertEquals(123, target.getNested().getValue());
210+
}
211+
212+
@Test
213+
public void testBindRelaxedNestedCamelValue() throws Exception {
214+
TargetWithNestedObject target = new TargetWithNestedObject();
215+
bind(target, "another_nested_foo_Baz: bar\n" + "another-nested_value: 123");
216+
assertEquals("bar", target.getAnotherNested().getFooBaz());
217+
assertEquals(123, target.getAnotherNested().getValue());
218+
}
219+
204220
@Test
205221
public void testBindNestedWithEnviromentStyle() throws Exception {
206222
TargetWithNestedObject target = new TargetWithNestedObject();
@@ -736,15 +752,27 @@ public void setNested(Set<String> nested) {
736752
}
737753

738754
public static class TargetWithNestedObject {
755+
739756
private VanillaTarget nested;
740757

758+
private VanillaTarget anotherNested;
759+
741760
public VanillaTarget getNested() {
742761
return this.nested;
743762
}
744763

745764
public void setNested(VanillaTarget nested) {
746765
this.nested = nested;
747766
}
767+
768+
public VanillaTarget getAnotherNested() {
769+
return this.anotherNested;
770+
}
771+
772+
public void setAnotherNested(VanillaTarget anotherNested) {
773+
this.anotherNested = anotherNested;
774+
}
775+
748776
}
749777

750778
public static class VanillaTarget {

0 commit comments

Comments
 (0)