-
Notifications
You must be signed in to change notification settings - Fork 156
Description
What problem are you trying to solve?
The current implementation of URLSearchParams has a significant flaw when working with multiple parameters of the same name. Both set() and append() methods ultimately result in data loss when the URL is processed by most backend frameworks (especially PHP, some Java servlets, and others).
Current behavior:
const params = new URLSearchParams();
params.append('category', 'books');
params.append('category', 'movies');
params.append('category', 'music');
console.log(params.toString()); // "category=books&category=movies&category=music"When this reaches a typical PHP backend:
// $_GET['category'] contains only 'music' - data loss!The problem:
- The API suggests support for multiple values via
append() - But the string representation is incompatible with how most backend systems handle repeated parameters
- This misleads developers into thinking they can safely use multiple values
- Results in silent data loss that's hard to debug
What solutions exist today?
Currently, developers must implement manual workarounds:
// Manual grouping
const groups = {};
['books', 'movies', 'music'].forEach(value => {
groups['category'] = groups['category'] ? groups['category'] + ',' + value : value;
});
// Then manually construct: "category=books,movies,music"
// Or use array notation manually
const params = ['books', 'movies', 'music'].map(v => `category[]=${v}`).join('&');
// "category[]=books&category[]=movies&category[]=music"These solutions are:
- Error-prone and require extra code
- Inconsistent across different codebases
- Not discoverable for new developers
How would you solve it?
Add an optional parameter to the constructor for logical grouping:
// Current behavior (default for backward compatibility)
const params1 = new URLSearchParams();
// OR
const params2 = new URLSearchParams({ groupMultiple: false });
// New grouped behavior
const params3 = new URLSearchParams({ groupMultiple: true });
params3.append('category', 'books');
params3.append('category', 'movies');
console.log(params3.toString()); // "category=books,movies"
// Alternative: array notation
const params4 = new URLSearchParams({ groupMultiple: 'brackets' });
params4.append('category', 'books');
params4.append('category', 'movies');
console.log(params4.toString()); // "category[]=books&category[]=movies"Additional methods could include:
params.getMultiple('category'); // ['books', 'movies'] - returns all values
params.toString({ groupMultiple: true }); // override default for this callAnything else?
Why this matters:
- Prevents silent data loss in production applications
- Aligns with how form data with multiple checkboxes typically works
- Provides a migration path from current behavior
- Makes the API actually useful for real-world form handling
Backward compatibility:
- Default behavior remains unchanged (
groupMultiple: false) - New behavior is opt-in via constructor parameter
- No breaking changes for existing code
This would make URLSearchParams actually practical for handling form data with multiple selections, rather than being a footgun that looks like it supports multiple values but actually doesn't work with common backend systems.