如何在 Rust serde 序列化程序中传播错误?

How do you propagate errors in a Rust serde serializer?

提问人:Michael 提问时间:6/29/2023 更新时间:6/29/2023 访问量:142

问:

我正在尝试实现 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_stringS::Error

我试过用这样的东西替换这条线:let

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 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

rust 错误处理 serde serde-json

评论


答:

6赞 cdhowie 6/29/2023 #1

该错误不是 serde 错误,但您可以将其包装在 serde 自定义错误中,如下所示:

use serde::{Serializer, ser::Error};

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(S::Error::custom)?;
    s.serialize_str(&string)
}

请注意,您需要导入,因为这是函数来源的特征。serde::ser::Errorcustom

评论

0赞 Michael 6/29/2023
在行中,和之间有区别吗?我无意中输入了前者,它编译了;我只是想知道我是否错过了微妙的差异。letError::customS::Error::custom
0赞 Matthieu M. 6/29/2023
@Michael:指序列化程序报告的错误,而指范围内的任何名称。后者更脆弱:您可能没有进入范围,或者您可能在范围中具有不同的符号(例如)。S::ErrorErrorErrorser::ErrorErrorstd::error::Error