Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix inconsistent query parameter conversion for String params #34713

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@
import jakarta.servlet.http.Part;
import org.jspecify.annotations.Nullable;

import org.springframework.beans.ConfigurablePropertyAccessor;
import org.springframework.beans.InvalidPropertyException;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyValue;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
Expand Down Expand Up @@ -73,6 +76,7 @@
*
* @author Juergen Hoeller
* @author Brian Clozel
* @author Sumin Kim
* @since 2.5.2
* @see #bind(org.springframework.web.context.request.WebRequest)
* @see #registerCustomEditor
Expand Down Expand Up @@ -167,6 +171,46 @@ else if (StringUtils.startsWithIgnoreCase(
doBind(mpvs);
}

/**
* Binds the given property values to this binder's target.
* <p>This implementation handles the case where string array values need to be
* converted to single string values if the property is not array-typed.
* <p>For properties that don't have the "[]" suffix but contain string array values,
* this method will use only the first array element when the target property
* is not of array type.
*
* @param mpvs the property values to bind
* @see #getTarget()
* @see #getPropertyAccessor()
*/
@Override
protected void doBind(MutablePropertyValues mpvs) {
Object target = getTarget();
if (target == null) {
super.doBind(mpvs);
return;
}

ConfigurablePropertyAccessor accessor = getPropertyAccessor();

for (PropertyValue pv : mpvs.getPropertyValues()) {
String propertyName = pv.getName();
Object value = pv.getValue();
if (!propertyName.endsWith("[]") && value instanceof String[] array && array.length > 0) {
try {
Class<?> propertyType = accessor.getPropertyType(propertyName);
if (propertyType == null || !propertyType.isArray()) {
mpvs.add(propertyName, new String[] { array[0] });
}
}
catch (InvalidPropertyException ex) {
mpvs.add(propertyName, new String[] { array[0] });
}
}
}
super.doBind(mpvs);
}

/**
* Treats errors as fatal.
* <p>Use this method only if it's an error if the input isn't valid.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@

/**
* @author Juergen Hoeller
* @author Sumin Kim
*/
class WebRequestDataBinderTests {

Expand Down Expand Up @@ -124,6 +125,18 @@ public void testFieldWithEmptyArrayIndex() {
assertThat(target.getStringArray()).containsExactly("ONE", "TWO");
}

@Test
public void testSameNameParameterFirstValueConversion() {
TestBean target = new TestBean();
WebRequestDataBinder binder = new WebRequestDataBinder(target);

MockHttpServletRequest request = new MockHttpServletRequest();
request.addParameter("touchy", "ONE");
request.addParameter("touchy", "TWO");
binder.bind(new ServletWebRequest(request));
assertThat(target.getTouchy()).isEqualTo("ONE");
}

@Test
void testFieldDefault() {
TestBean target = new TestBean();
Expand Down