将 Rust 结构的泛型参数约束为反序列化

Constraining generic parameter of Rust struct to be Deserialize

我想将可(反)序列化结构限制为具有也可反序列化的通用参数。派生宏 Deserialize 不需要我添加此约束,这很好,但我希望集成代码得到编译错误,即使它们从不尝试反序列化库中定义的结构。

use failure::Fallible; // 0.1.6
use serde::{Deserialize, Serialize}; // 1.0.104
use serde_json::to_string_pretty; // 1.0.44

#[derive(Deserialize, Serialize)]
struct X<T>
where
    // T: Serialize,
{
    a: u8,
    t: T,
}

type Main<'a> = &'a dyn Fn() -> Fallible<()>;

fn main() -> Fallible<()> {
    let x = X { a: 1, t: false };
    println!("{}", to_string_pretty(&x)?);

    let y: X<bool> = serde_json::from_str(r#"{"a":2,"t":true}"#)?;
    println!("{}", y.t);

    let _z: X<Main> = X { a: 3, t: &main };
    // println!("{}", to_string_pretty(&z)?);

    //let w: X<Main> = serde_json::from_str(r#"{"a":4,"t":NONONO}"#)?;

    Ok(())
}

playground

我试图将 where for<'a> T: serde::de::Deserialize<'a> 添加为 struct X<T> 的约束,但即使没有使用 X

也会破坏构建
use serde::{Deserialize, Serialize};

#[derive(Deserialize, Serialize)]
struct X<T>
where
    for<'a> T: serde::de::Deserialize<'a>,
{
    a: u8,
    t: T,
}

playground

有没有办法表达我正在寻找的这个限制条件?

您需要使用 #[serde(bound)] 来防止 Serde 尝试自动确定 DeserializeSerialize 实现的边界:

use serde::{Deserialize, Serialize};

#[derive(Deserialize, Serialize)]
#[serde(bound = "T: Serialize, for<'de2> T: Deserialize<'de2>")]
struct X<T>
where
    T: Serialize,
    for<'de2> T: Deserialize<'de2>,
{
    t: T,
}

struct NotSerializable;

fn main() {
    X { t: true };

    // X { t: NotSerializable }; // Generates compiler error
}

另请参阅:

  • Rust and serde deserializing using generics