自定义serde序列化器时,如何为serde::ser::Error实现Debug?
解决Serde自定义错误类型的
Debug实现问题 问题核心是Box<dyn Display>未实现Debug,但你的Error类型需要满足std::error::Error对Debug的要求,同时不能违反serde::ser::Error的trait约定(即custom方法的参数只能有Display约束)。下面提供两种可行的解决方式:
方案一:手动实现Debug trait
无需修改Error枚举的变体定义,直接为Error手动编写Debug实现,对Custom变体用其内部Display的输出作为Debug格式内容:
use std::fmt::{Debug, Display, Formatter}; pub enum Error { Custom(Box<dyn Display>), CannotSerializeMap, } // 手动实现Debug,绕过Box<dyn Display>无Debug的问题 impl Debug for Error { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { Self::Custom(err) => write!(f, "Custom({})", err), Self::CannotSerializeMap => f.write_str("CannotSerializeMap"), } } } impl Display for Error { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { Self::Custom(error) => Display::fmt(error, f), Self::CannotSerializeMap => write!(f, "cannot serialize map"), } } } impl std::error::Error for Error {} impl serde::ser::Error for Error { fn custom<T>(msg: T) -> Self where T: Display + 'static, // 静态生命周期约束满足Box<dyn Display>的要求 { Self::Custom(Box::new(msg)) } }
方案二:用包装器统一实现Display + Debug
定义一个包装结构体,让任意实现Display的类型通过它自动获得Debug实现,再将Error的Custom变体改为存储Box<dyn Display + Debug>,这样就能直接派生Debug:
use std::fmt::{Debug, Display, Formatter}; // 包装器:为任意Display类型添加Debug实现 struct DebugDisplay<T>(T); impl<T: Display> Display for DebugDisplay<T> { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { self.0.fmt(f) } } impl<T: Display> Debug for DebugDisplay<T> { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { // 复用Display的输出作为Debug内容 write!(f, "{}", self.0) } } #[derive(Debug)] pub enum Error { Custom(Box<dyn Display + Debug + 'static>), CannotSerializeMap, } impl Display for Error { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { Self::Custom(error) => Display::fmt(error, f), Self::CannotSerializeMap => write!(f, "cannot serialize map"), } } } impl std::error::Error for Error {} impl serde::ser::Error for Error { fn custom<T>(msg: T) -> Self where T: Display + 'static, { Self::Custom(Box::new(DebugDisplay(msg))) } }
内容的提问来源于stack exchange,提问作者user22747722
相关产品推荐
相关产品推荐

