如何在Rust Serde序列化器中传递错误?
问题
我正尝试实现Serde的serialize_with属性,现有代码如下:
use serde::Serializer; pub fn serialize_json_as_string<S>(json: &serde_json::value::Value, s: S) -> Result<S::Ok, S::Error> where S: Serializer, { let string = serde_json::to_string(json).unwrap(); s.serialize_str(&string) }
我不想用倒数第二行的unwrap(),但没法把to_string返回的错误转换成<S::Error>。尝试用let string = serde_json::to_string(json)?;替换时,出现报错:
error[E0277]: `?` couldn't convert the error to `<S as serde::Serializer>::Error` --> src/model/field_type.rs:30:45 | 26 | pub fn serialize_json_as_string<S>(json: &serde_json::value::Value, s: S) -> Result<S::Ok, S::Error> | ----------------------- expected `<S as serde::Serializer>::Error` because of this ... 30 | let string = serde_json::to_string(json)?; | ^ the trait `From<serde_json::Error>` is not implemented for `<S as serde::Serializer>::Error` | = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait = note: required for `Result<<S as serde::Serializer>::Ok, <S as serde::Serializer>::Error>` to implement `FromResidual<Result<Infallible, serde_json::Error>>` help: consider further restricting the associated type | 28 | S: Serializer, <S as serde::Serializer>::Error: From<serde_json::Error> | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ For more information about this error, try `rustc --explain E0277`.
换成match语句也遇到类似错误:
match serde_json::to_string(json) { Ok(string) => s.serialize_str(&string), Err(e) => Err(e.into()), }
报错信息:
error[E0277]: the trait bound `<S as serde::Serializer>::Error: From<serde_json::Error>` is not satisfied --> src/model/field_type.rs:32:25 | 32 | Err(e) => Err(e.into()), | ^^^^ the trait `From<serde_json::Error>` is not implemented for `<S as serde::Serializer>::Error` | = note: required for `serde_json::Error` to implement `Into<<S as serde::Serializer>::Error>` help: consider further restricting the associated type | 28 | S: Serializer, <S as serde::Serializer>::Error: From<serde_json::Error> | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ For more information about this error, try `rustc --explain E0277`.
因为我没法修改Serde的代码,没法实现Into转换,不知道该怎么手动转换这个错误。
解决方案
Serde的Serializer trait关联的错误类型必须实现serde::ser::Error trait,这个 trait 提供了custom方法,可将任意字符串形式的错误信息转换为序列化器的错误类型。利用这个方法就能处理serde_json::Error:
修改后的代码如下:
use serde::ser::Error; use serde::Serializer; pub fn serialize_json_as_string<S>(json: &serde_json::value::Value, s: S) -> Result<S::Ok, S::Error> where S: Serializer, { let string = serde_json::to_string(json) .map_err(|e| S::Error::custom(format!("JSON序列化失败: {}", e)))?; s.serialize_str(&string) }
关键点说明
- 引入必要的trait:需要导入
serde::ser::Error才能使用custom方法。 - 错误转换:通过
map_err将serde_json::Error转换为S::Error,custom方法会把错误信息包装成当前序列化器要求的错误类型。 - 安全替代unwrap:使用
?操作符处理转换后的Result,彻底避免unwrap()可能导致的程序崩溃。
如果不需要自定义错误前缀,也可以直接传递错误的默认字符串表示:
.map_err(|e| S::Error::custom(e.to_string()))?;
内容的提问来源于stack exchange,提问作者Michael
相关产品推荐
相关产品推荐

