我写了一个自定义的
chrono::DateTime<Utc>
序列化器:
pub mod datetime {
pub fn serialize<S: Serializer>(
date: &DateTime<Utc>,
serializer: S,
) -> Result<S::Ok, S::Error> {
// ...
}
// deserialize omitted
}
我需要为
struct
实现自定义序列化逻辑,并且在将 serde(with = "datetime")
的行为模拟为结构体字段上的属性时遇到困难。我想要复制的内容:
#[derive(Serialize, Deserialize)]
struct Foo {
#[serde(with = "datetime")]
pub timestamp: DateTime<Utc>,
}
我的尝试:
impl Serialize for Foo {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let mut m = serializer.serialize_map(None)?;
m.serialize_entry(
"timestamp",
&datetime::serialize(&self.timestamp, serializer)?,
)?;
m.end()
}
}
导致错误:
error[E0277]: the trait bound `<S as foo::_::_serde::Serializer>::Ok: Serialize` is not satisfied
--> <...>/foo.rs:95:13
|
93 | m.serialize_entry(
| --------------- required by a bound introduced by this call
94 | "timestamp",
95 | &datetime::serialize(&self.sent_timestamp, serializer)?,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Serialize` is not implemented for `<S as foo::_::_serde::Serializer>::Ok`
|
note: required by a bound in `serialize_entry`
--> ~/.cargo/registry/src/index.crates.io-6f17d22bba15001f/serde-1.0.193/src/ser/mod.rs:1808:12
|
1801 | fn serialize_entry<K: ?Sized, V: ?Sized>(
| --------------- required by a bound in this associated function
...
1808 | V: Serialize,
| ^^^^^^^^^ required by this bound in `SerializeMap::serialize_entry`
help: consider further restricting the associated type
|
86 | fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> where <S as foo::_::_serde::Serializer>::Ok: Serialize {
|
我是否误解了
Serializer
的用法?我不完全确定我在这里做错了什么。
正如评论中所建议的,使用
#[derive(Serialize)]
查看 #[serde(with)]
的扩展将帮助我们了解派生代码到底在做什么,从而使我们能够复制其行为。这可以通过将代码复制到 Rust Playground 并使用“工具”下拉菜单中的“扩展宏”选项来完成。
在查看扩展的代码时,我们看到如下所示的内容(尽管我已经对其进行了重大清理以使其更具可读性):
struct SerializeWith<'a>(&'a DateTime<Utc>);
impl Serialize for SerializeWith<'_> {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
datetime::serialize(&self.0, serializer)
}
}
因此,正确的方法是定义一个直接调用自定义序列化逻辑的新类型。完整正确的
Serialize
实现是:
impl Serialize for Foo {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
struct SerializeWith<'a>(&'a DateTime<Utc>);
impl Serialize for SerializeWith<'_> {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
datetime::serialize(&self.0, serializer)
}
}
let mut m = serializer.serialize_struct("Foo", 1)?;
m.serialize_field("timestamp", &SerializeWith(&self.timestamp))?;
m.end()
}
}