use serde::{Deserialize, Serialize}; #[derive(Clone, Debug, PartialEq)] pub enum TriState { None, Null, Some(T), } impl TriState { // pub fn is_some(&self) -> bool { // matches!(self, TriState::Some(_)) // } // pub fn is_null(&self) -> bool { // matches!(self, TriState::Null) // } pub fn is_none(&self) -> bool { matches!(self, TriState::None) } } impl Default for TriState { fn default() -> Self { TriState::None } } impl Serialize for TriState where T: Serialize, { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, { match self { TriState::None => serializer.serialize_none(), TriState::Null => serializer.serialize_unit(), TriState::Some(value) => value.serialize(serializer), } } } impl<'de, T> Deserialize<'de> for TriState where T: Deserialize<'de>, { fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de>, { let opt = Option::::deserialize(deserializer); match opt { Ok(Some(value)) => Ok(TriState::Some(value)), Ok(None) => Ok(TriState::Null), Err(_) => Ok(TriState::None), } } } impl From> for TriState { fn from(option: Option) -> Self { match option { Some(value) => TriState::Some(value), None => TriState::Null, } } } #[derive(Serialize)] #[serde(transparent)] pub struct TriStateField { #[serde(skip_serializing_if = "TriState::is_none")] pub value: TriState, } impl From> for TriStateField { fn from(value: TriState) -> Self { TriStateField { value } } } impl From> for TriState { fn from(field: TriStateField) -> Self { field.value } } #[cfg(test)] mod tests { use super::*; #[derive(Debug, PartialEq, Serialize, Deserialize)] struct TestStruct { required: String, optional: Option, #[serde(skip_serializing_if = "TriState::is_none")] tristate: TriState, } #[test] fn test_tristate_serialization() { // 创建三个测试结构体,分别包含不同状态的TriState let test_none = TestStruct { required: "必填字段".to_string(), optional: Some("可选字段".to_string()), tristate: TriState::None, }; let test_null = TestStruct { required: "必填字段".to_string(), optional: None, tristate: TriState::Null, }; let test_some = TestStruct { required: "必填字段".to_string(), optional: Some("可选字段".to_string()), tristate: TriState::Some("三态字段".to_string()), }; // 序列化并打印结果 println!("TriState::None 序列化结果:"); println!("{}", serde_json::to_string_pretty(&test_none).unwrap()); println!(); println!("TriState::Null 序列化结果:"); println!("{}", serde_json::to_string_pretty(&test_null).unwrap()); println!(); println!("TriState::Some 序列化结果:"); println!("{}", serde_json::to_string_pretty(&test_some).unwrap()); println!(); // 验证序列化行为 let json_none = serde_json::to_string(&test_none).unwrap(); let json_null = serde_json::to_string(&test_null).unwrap(); let json_some = serde_json::to_string(&test_some).unwrap(); // TriState::None 不应该在JSON中出现 assert!(!json_none.contains("tristate")); // TriState::Null 应该在JSON中出现为null assert!(json_null.contains("\"tristate\":null")); // TriState::Some 应该在JSON中出现为具体值 assert!(json_some.contains("\"tristate\":\"三态字段\"")); } }