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
相关产品推荐
相关产品推荐

