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

Inconsistent Query Parameter Conversion When Mapping Multiple Values to a Single Parameter #34613

Closed
spirosag opened this issue Mar 17, 2025 · 1 comment
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) status: declined A suggestion or change that we don't feel we should currently apply

Comments

@spirosag
Copy link

spirosag commented Mar 17, 2025

There is a significant inconsistency when converting a query parameter from a collection to a single value. In the following example controller, the value received by the method varies unpredictably when multiple values are provided, leading to inconsistent behavior.

@RestController
public class SampleController {
    
    @PostMapping("/myIntegerParam")
    public String printIntegerParameter(@RequestParam(required = false) Integer param) {
        System.out.println("Query parameter: " + param);
        return "Received param: " + param;
    }

    @PostMapping("/myStringParam")
    public String printStringParameter(@RequestParam(required = false) String param) {
        System.out.println("Query parameter: " + param);
        return "Received param: " + param;
    }
}

If you send a /myIntegerParam?param=1&param=2 request, the printIntegerParameter() method will only receive the first value 1.
But if you send a /myStringParam?param=1&param=2 request, the printStringParameter() method will receive both values comma separated as a single string: 1,2

The reason why this is happening is because in the 1st case the conversion is handled by the org.springframework.core.convert.support.ArrayToObjectConverter class, while in the 2nd by the org.springframework.core.convert.support.ArrayToStringConverter class.

I'm not sure whether this is a deliberate design decision or simply Spring delegating the conversion in its standard way. However, for a query parameter, this behavior introduces several issues:

  1. Inconsistency – This approach is inconsistent with how other types are handled (e.g., integers in my example). For most types, Spring keeps only the first value, but for strings, it concatenates them. Why should a developer expect this discrepancy?

  2. Lack of Practical Use – The resulting value is not meaningful. It is neither the first nor the last provided value, nor any actual value passed. This makes it unclear how a developer should handle it.

  3. Incorrect Assumption – If a developer intended to get multiple values, they would have used a list rather than a single string.

  4. Unnecessary Complexity – Given that string query parameters are extremely common, this unusual behavior forces developers to add extra validations and custom converters to ensure expected behavior.

To maintain consistency, the best approach when converting multiple query parameters into a single value is to always return the same value (either the first or last)

The above behavior was observed with:

  • 'org.springframework.boot' version '3.4.3'
  • 'org.springframework:spring-core' version '6.2.3'
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Mar 17, 2025
@jhoeller jhoeller added the in: web Issues in web modules (web, webmvc, webflux, websocket) label Mar 19, 2025
@bclozel
Copy link
Member

bclozel commented Apr 7, 2025

Thank you for your thoughtful submission and for bringing this matter to our attention. After an exhaustive review and contemplation of the circumstances, I regret to inform you that we will not be proceeding with your proposed change regarding the query parameter conversion behavior. Please allow me to elaborate on several key factors that inform this decision.

Firstly, it’s crucial to recognize that the behavior you are highlighting is, in fact, entirely consistent with the broader conversion paradigms established within this project. For example, string concatenation has been a longstanding and deliberate choice within our system, wherein strings are gracefully concatenated without issue. However, as you’ve noted, integer concatenation does not exhibit the same pattern, because it's simply not possible. This discrepancy is not an inconsistency, but rather a design choice rooted in foundational data type handling.

Furthermore, I would like to emphasize that this specific conversion behavior has been enforced and consistent for many years. It has been thoroughly tested, vetted, and understood by a wide array of users and contributors. Any changes to this fundamental behavior would not only risk destabilizing long-standing functionality but would also introduce potential breaking changes to the many systems relying on it. In such cases, the importance of backwards compatibility cannot be overstated. As a project, we have always prioritized preserving the integrity of previous implementations, which serves as the foundation for ensuring that users can rely on consistent and dependable functionality, especially in production environments.

Thank you once again for your submission.

@bclozel bclozel closed this as not planned Won't fix, can't repro, duplicate, stale Apr 7, 2025
@bclozel bclozel added status: declined A suggestion or change that we don't feel we should currently apply and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Apr 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) status: declined A suggestion or change that we don't feel we should currently apply
Projects
None yet
4 participants