You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Actix Web中如何正确传递查询字符串数组参数?

Actix Web接收查询字符串数组参数的正确方式

问题场景

尝试实现Actix Web端点接收查询字符串中的数组参数,现有代码如下:

use actix_web::{get, web, App, HttpResponse, HttpServer};
use serde::Deserialize;

#[derive(Deserialize)]
struct Query {
    x: Vec<i32>,
}

#[get("/test")]
async fn test(query: web::Query<Query>) -> HttpResponse {
    println!("{:?}", query.x);
    HttpResponse::Ok().finish()
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        App::new().service(test)
    }).bind(("localhost", 8080))?.run().await
}

遇到两种错误:

  1. 调用http://localhost:8080/test?x=25时,报错:
Query deserialize error: invalid type: string "25", expected a sequence
  1. 调用http://localhost:8080/test?x[]=25&x[]=36时,报错:
Query deserialize error: missing field `x`

Cargo.toml配置:

[package]
name = "actix-qs-check"
version = "0.1.0"
edition = "2024"

[dependencies]
actix-web = "4.9.0"
serde = { version = "1.0.217", features = ["derive"] }

工具链:rustc 1.85.0-nightly (21fe748be 2024-12-11)

解决方案(无需serde_qs)

方案1:使用标准重复Key格式

Actix Web默认的web::Query基于serde_urlencoded实现,它通过重复同一个查询参数Key来解析数组。直接调用:

http://localhost:8080/test?x=25&x=36

现有代码无需修改即可正确解析出Vec<i32>。

如果需要兼容单个值的情况(比如?x=25也能解析为包含一个元素的Vec),可以添加自定义反序列化逻辑:

use actix_web::{get, web, App, HttpResponse, HttpServer};
use serde::Deserialize;
use serde::de::{Deserializer, Error};

// 辅助函数:支持单个值或多个重复值反序列化为Vec
fn single_or_vec<'de, D, T>(deserializer: D) -> Result<Vec<T>, D::Error>
where
    D: Deserializer<'de>,
    T: Deserialize<'de>,
{
    let value: serde_json::Value = Deserialize::deserialize(deserializer)?;
    match value {
        serde_json::Value::Array(arr) => arr.into_iter().map(T::deserialize).collect(),
        _ => T::deserialize(value).map(|item| vec![item]),
    }
}

#[derive(Deserialize)]
struct Query {
    #[serde(deserialize_with = "single_or_vec")]
    x: Vec<i32>,
}

// 后续test和main函数保持不变

这样无论传单个x=25还是多个x=25&x=36都能正常解析。

方案2:兼容x[]格式

如果需要支持x[]=25&x[]=36这种格式,只需给结构体字段添加重命名属性:

#[derive(Deserialize)]
struct Query {
    #[serde(rename = "x[]")]
    x: Vec<i32>,
}

此时调用http://localhost:8080/test?x[]=25&x[]=36即可正确解析。若要兼容单个x[]=25,同样可以结合上面的single_or_vec辅助函数。

错误原因解析

  • 调用?x=25报错:serde默认期望x是序列(即多个重复的x参数),但实际收到单个字符串值,类型不匹配。
  • 调用?x[]=25&x[]=36报错:结构体字段名为x,但查询参数是x[],serde找不到对应字段导致缺失错误。

内容的提问来源于stack exchange,提问作者Fomalhaut

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 07:17:01