共计 2834 个字符,预计需要花费 8 分钟才能阅读完成。
背景痛点
在前后端分离开发中,我们经常需要将前端的数据通过 AJAX 传递到后端。对于简单的键值对参数,使用传统的 URL 参数拼接方式(如key1=value1&key2=value2)就能轻松搞定。但当涉及到数组参数时,这种方式就会遇到各种问题。

- PHP 的
$_GET数组化问题 - 当传递
arr=1&arr=2时,PHP 的$_GET['arr']只会获取到最后一个值2 -
必须使用
arr[]=1&arr[]=2这种特殊格式才能正确解析为数组 -
Spring MVC 的
@RequestParam绑定失败 - 默认情况下,
@RequestParam无法直接接收数组参数 -
需要显式声明为
@RequestParam("arr[]")或使用特殊处理 -
URL 长度限制
- 当数组元素较多时,URL 可能会超过浏览器或服务器的限制
- 导致请求被截断或拒绝
技术方案对比
URL 编码方案
这是最传统的解决方案,通过特定的参数格式来传递数组:
- 参数格式
- 使用
arr[]=1&arr[]=2的形式 -
或者
arr=1&arr=2(取决于后端框架支持) -
Content-Type
- 默认使用
application/x-www-form-urlencoded -
浏览器会自动处理参数的编码
-
优点
- 兼容性最好,几乎所有服务器框架都支持
-
可以直接在 URL 中使用(GET 请求)
-
缺点
- 不适合传递复杂数据结构
- 存在 URL 长度限制
- 需要处理特殊字符的转义
JSON 序列化方案
这是更现代的解决方案,特别适合复杂数据结构:
- 参数格式
- 使用
JSON.stringify()将数组转换为 JSON 字符串 -
示例:
{"arr":[1,2,3]} -
Content-Type
- 必须设置为
application/json -
需要显式设置请求头
-
优点
- 可以传递任意复杂的数据结构
- 不受 URL 长度限制
-
现代框架都能自动解析
-
缺点
- 旧版服务器可能需要额外配置
- GET 请求无法使用
代码实现
jQuery 实现
// URL 编码方式
$.ajax({
url: '/api/data',
method: 'POST',
data: {'arr[]': [1, 2, 3] // jQuery 会自动处理数组参数
},
traditional: true, // 防止 jQuery 深度序列化
success: function(response) {console.log('Success:', response);
},
error: function(xhr) {console.error('Error:', xhr.statusText);
}
});
// JSON 方式
$.ajax({
url: '/api/data',
method: 'POST',
contentType: 'application/json',
data: JSON.stringify({arr: [1, 2, 3]
}),
success: function(response) {console.log('Success:', response);
},
error: function(xhr) {console.error('Error:', xhr.statusText);
}
});
Axios 实现
// URL 编码方式
axios.post('/api/data', {'arr[]': [1, 2, 3]
}, {
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
transformRequest: [function(data) {return Qs.stringify(data, {arrayFormat: 'brackets'});
}]
}).then(response => {console.log('Success:', response.data);
}).catch(error => {console.error('Error:', error);
});
// JSON 方式
axios.post('/api/data', {arr: [1, 2, 3]
}, {
headers: {'Content-Type': 'application/json'}
}).then(response => {console.log('Success:', response.data);
}).catch(error => {console.error('Error:', error);
});
Fetch 实现
// URL 编码方式
const formData = new FormData();
[1, 2, 3].forEach(item => {formData.append('arr[]', item);
});
fetch('/api/data', {
method: 'POST',
body: formData
}).then(response => {if (!response.ok) throw new Error('Network error');
return response.json();}).then(data => {console.log('Success:', data);
}).catch(error => {console.error('Error:', error);
});
// JSON 方式
fetch('/api/data', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({arr: [1, 2, 3]
})
}).then(response => {if (!response.ok) throw new Error('Network error');
return response.json();}).then(data => {console.log('Success:', data);
}).catch(error => {console.error('Error:', error);
});
生产建议
- 特殊字符处理
- URL 中的
+号会被解码为空格 - 应该使用
encodeURIComponent()进行编码 -
JSON 中要注意双引号的转义
-
服务端兼容性
- 建议同时支持
application/json和form-data -
可以添加中间件自动解析不同格式
-
性能考虑
- 小数据量:URL 编码更快
- 大数据量:JSON 更高效(体积更小)
- 实测表明,当数组元素超过 100 个时,JSON 优势明显
延伸思考
对于更复杂的嵌套数据结构,如对象数组:
const data = {
users: [{id: 1, name: 'Alice'},
{id: 2, name: 'Bob'}
]
};
- 解决方案
- 必须使用 JSON 序列化
-
可以考虑使用更高效的数据格式(如 Protocol Buffers)
-
推荐阅读
- RESTful API 设计规范
- GraphQL 等现代 API 技术
- 各种数据序列化格式对比
在实际项目中,选择哪种方案取决于你的具体需求和技术栈。对于大多数现代应用,JSON 序列化是更推荐的方式,特别是当你的数据结构比较复杂时。而对于简单的场景或者需要兼容旧系统的情况,URL 编码仍然是可靠的备选方案。
正文完
