You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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)
}

关键点说明

  1. 引入必要的trait:需要导入serde::ser::Error才能使用custom方法。
  2. 错误转换:通过map_err将serde_json::Error转换为S::Error,custom方法会把错误信息包装成当前序列化器要求的错误类型。
  3. 安全替代unwrap:使用?操作符处理转换后的Result,彻底避免unwrap()可能导致的程序崩溃。

如果不需要自定义错误前缀,也可以直接传递错误的默认字符串表示:

.map_err(|e| S::Error::custom(e.to_string()))?;

内容的提问来源于stack exchange,提问作者Michael

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 10:54:51