如何声明包含任何可反序列化/可序列化的结构的结构?

时间:2019-06-30 14:34:10

标签: rust serde

我试图声明一个包含任何给定类型的其他结构的结构,这些结构可以是DeserializeSerialize

#[derive(Debug, Serialize, Deserialize)]
pub struct Foo<T: Deserialize + Serialize> {
    pub data: T,
}

Rust playground

为此,我尝试使用特征范围,例如使用DeserializeOwnedDeserialize等特征。两者都在编译时失败,并出现以下错误:

error[E0283]: type annotations required: cannot resolve `T: serde::Deserialize<'de>`
 --> src/main.rs:9:28
  |
9 | #[derive(Debug, Serialize, Deserialize)]
  |                            ^^^^^^^^^^^
  |
  = note: required by `serde::Deserialize`
error[E0637]: `&` without an explicit lifetime name cannot be used here
  --> src/main.rs:10:19
   |
10 | pub struct Foo<T: Deserialize + Serialize> {
   |                   ^^^^^^^^^^^ explicit lifetime name needed here

由于我没有使用存储引用而是存储值,因此在尝试添加生命周期时遇到了错误。

声明这种结构的最惯用的方法是什么?

2 个答案:

答案 0 :(得分:1)

我找到了一个解决方案,这要归功于Rust Discord的一名成员,他将我推荐给了以下Github issue。诀窍不是使用特征范围而是属性范围。

#[derive(Debug, Serialize, Deserialize)]
pub struct Foo<T> {
    #[serde(bound(
        serialize = "T: Serialize",
        deserialize = "T: Deserialize<'de>",
    ))]
    pub data: T,
}

答案 1 :(得分:1)

请不要将边界放在类型上

use serde::{Deserialize, Serialize}; // 1.0.91

#[derive(Debug, Serialize, Deserialize)]
pub struct Foo<T> {
    pub data: T,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Boo {
    pub a: i64,
}

fn main() {
    let data = Boo { a: 1 };
    let wrap = Foo { data };
    println!("{:?}", wrap);
}

然后,将边界放在需要该行为的方法上:

fn use_it<T>(foo: Foo<T>)
where
    Foo<T>: Serialize,
{
    // ...
}