From 90f17a9e675eced0bf235703f9097ecaac4ee1a7 Mon Sep 17 00:00:00 2001
From: kssumin <201566@jnu.ac.kr>
Date: Thu, 3 Apr 2025 19:35:22 +0900
Subject: [PATCH] Fix inconsistent query parameter conversion for String params

Signed-off-by: kssumin <201566@jnu.ac.kr>
---
 .../bind/support/WebRequestDataBinder.java    | 44 +++++++++++++++++++
 .../support/WebRequestDataBinderTests.java    | 13 ++++++
 2 files changed, 57 insertions(+)

diff --git a/spring-web/src/main/java/org/springframework/web/bind/support/WebRequestDataBinder.java b/spring-web/src/main/java/org/springframework/web/bind/support/WebRequestDataBinder.java
index 1e393922f304..eab6e684d5f1 100644
--- a/spring-web/src/main/java/org/springframework/web/bind/support/WebRequestDataBinder.java
+++ b/spring-web/src/main/java/org/springframework/web/bind/support/WebRequestDataBinder.java
@@ -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;
@@ -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
@@ -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.
diff --git a/spring-web/src/test/java/org/springframework/web/bind/support/WebRequestDataBinderTests.java b/spring-web/src/test/java/org/springframework/web/bind/support/WebRequestDataBinderTests.java
index cc89017f3624..8e1fdd961bfd 100644
--- a/spring-web/src/test/java/org/springframework/web/bind/support/WebRequestDataBinderTests.java
+++ b/spring-web/src/test/java/org/springframework/web/bind/support/WebRequestDataBinderTests.java
@@ -40,6 +40,7 @@
 
 /**
  * @author Juergen Hoeller
+ * @author Sumin Kim
  */
 class WebRequestDataBinderTests {
 
@@ -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();