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

Rust+Actix-web RESTful API查询:布尔值反序列化异常解决

解决方案:处理serde_qs字符串转布尔值的反序列化问题

问题根源

serde_qs解析URL查询参数时,会将[true]这类数组参数解析为Vec<String>而非Vec<bool>,而你的SingleSelectFilter中value字段定义为Vec<bool>,因此触发类型不匹配错误。


方法1:自定义反序列化函数

针对Vec<bool>类型编写自定义反序列化逻辑,将字符串形式的"true"/"false"转换为布尔值:

use serde::{Deserialize, Deserializer};
use serde::de::Error;

// 处理单个字符串转布尔值
fn str_to_bool(s: &str) -> Result<bool, impl Error> {
    match s.to_lowercase().as_str() {
        "true" => Ok(true),
        "false" => Ok(false),
        _ => Err(Error::invalid_value(
            serde::de::Unexpected::Str(s),
            &"\"true\" or \"false\"",
        )),
    }
}

// 处理字符串数组转布尔数组
fn deserialize_bool_vec<'de, D>(deserializer: D) -> Result<Vec<bool>, D::Error>
where
    D: Deserializer<'de>,
{
    let str_values = Vec::<String>::deserialize(deserializer)?;
    str_values.into_iter()
        .map(|s| str_to_bool(&s))
        .collect()
}

在你的过滤结构体中应用该反序列化函数:

#[derive(Deserialize, Debug)]
struct SingleSelectFilter {
    operator: String,
    #[serde(deserialize_with = "deserialize_bool_vec")]
    value: Vec<bool>,
}

// 假设你的Filter枚举定义如下
#[derive(Deserialize, Debug)]
enum Filter {
    SingleSelect(SingleSelectFilter),
    // 其他过滤类型...
}

#[derive(Deserialize, Debug)]
struct FilterRequest {
    filter: Filter,
}

方法2:利用TryFrom trait结合serde属性

实现String到bool的TryFrom转换,再通过serde的try_from属性自动处理:

use serde::{Deserialize};
use std::convert::TryFrom;

impl TryFrom<String> for bool {
    type Error = String;

    fn try_from(s: String) -> Result<Self, Self::Error> {
        match s.to_lowercase().as_str() {
            "true" => Ok(true),
            "false" => Ok(false),
            _ => Err(format!("无效的布尔值字符串: {}", s)),
        }
    }
}

// 针对Vec<bool>实现转换
impl TryFrom<Vec<String>> for Vec<bool> {
    type Error = String;

    fn try_from(str_vec: Vec<String>) -> Result<Self, Self::Error> {
        str_vec.into_iter()
            .map(bool::try_from)
            .collect()
    }
}

然后在结构体中使用:

#[derive(Deserialize, Debug)]
struct SingleSelectFilter {
    operator: String,
    #[serde(try_from = "Vec<String>")]
    value: Vec<bool>,
}

替代方案:调整查询参数解析策略

如果不想自定义反序列化逻辑,也可以考虑:

  • 将value字段暂时定义为Vec<String>,在业务逻辑中手动转换为Vec<bool>后再生成MongoDB过滤文档

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 09:25:25