在Java Spring Web等框架中,我们可以收集重复的Query或者Form参数到一个列表中,就像这样:
@GetMapping
public String getValues(@RequestParam String[] values) {
return String.join(values, ",");
}
我们只要按照这种方式访问接口就可以将参数作为数组传递到后端:
curl "http://localhost:8080/test?values=value1&values=value2"
但是axum默认的Form和Query提取器是不支持这种玩法的。
解决方法其实很简单,就一句话:下载一个包:axum-extra,使用其中提供的Form提取器。(这个Form对GET请求会解析参数,效果是和Query一样的)。这个包是axum官方项目的一部分。示例代码:
use axum::{
http::StatusCode,
routing::{get, post},
};
use axum_extra::extract::Form;
use tokio::net::TcpListener;
#[derive(serde::Deserialize, Debug)]
pub struct TestParam {
#[serde(rename = "value")]
pub values: Vec<String>,
}
async fn test(Form(params): Form<TestParam>) -> Result<String, (StatusCode, String)> {
Ok(params.values.join(","))
}
#[tokio::main]
async fn main() {
let app = axum::Router::new()
.route("/test", post(test))
.route("/test", get(test));
let tcp_listener = TcpListener::bind("0.0.0.0:3000").await.unwrap();
axum::serve(tcp_listener, app.into_make_service())
.await
.unwrap();
}
不管是用GET + query参数还是用POST + 表单参数都可以正常地识别数组参数了。
如果在values的serde注解中再加一个(default)的话还可以兼容空数组(也就是什么都没有传入的情况)。
不得不说,官方是真能藏,这么有用的东西不管是文档还是issue里面都没有提到一下,发现这个东西的存在纯属误打误撞,希望后面的人看到这篇文章就不要再去绕弯路了。