如何使用serde将JSON中"SI"/"NO"字符串字段反序列化为bool类型
实现方案
最简单的方式是使用serde提供的deserialize_with字段属性,绑定自定义的反序列化函数即可,步骤如下:
1. 引入依赖
确保你的Cargo.toml中已经引入serde相关依赖并开启derive特性:
serde = { version = "1.0", features = ["derive"] } serde_json = "1.0"
2. 编写自定义反序列化函数
use serde::{Deserialize, de::Deserializer}; fn si_no_to_bool<'de, D>(deserializer: D) -> Result<bool, D::Error> where D: Deserializer<'de>, { let s: &str = Deserialize::deserialize(deserializer)?; match s { "SI" => Ok(true), "NO" => Ok(false), other => Err(serde::de::Error::custom(format!("无效值:{},仅支持SI或NO", other))), } }
3. 给结构体字段绑定反序列化逻辑
#[derive(Deserialize)] pub struct Entry { #[serde(deserialize_with = "si_no_to_bool")] pub foo: bool, }
测试示例
fn main() -> Result<(), Box<dyn std::error::Error>> { // 测试SI映射为true let json_si = r#"{"foo": "SI"}"#; let entry_si: Entry = serde_json::from_str(json_si)?; assert!(entry_si.foo); // 测试NO映射为false let json_no = r#"{"foo": "NO"}"#; let entry_no: Entry = serde_json::from_str(json_no)?; assert!(!entry_no.foo); Ok(()) }
复用方案(可选)
如果你有多个字段都需要用到SI/NO转bool的逻辑,可以封装为透明newtype避免重复写属性:
#[derive(Deserialize)] #[serde(transparent)] pub struct SiNoBool(#[serde(deserialize_with = "si_no_to_bool")] pub bool); // 使用时直接指定类型即可 #[derive(Deserialize)] pub struct Entry { pub foo: SiNoBool, // 其他同类型字段直接复用SiNoBool即可 pub bar: SiNoBool, } // 取值时访问.0即可 // let foo_val = entry.foo.0;
内容的提问来源于stack exchange,提问作者Overdrivr
相关产品推荐
相关产品推荐

