限制 Rust 结构体的泛型参数进行反序列化

wig*_*igy 4 generics rust serde

我想限制可(反)序列化的结构具有也可反序列化的通用参数。派生宏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(())
}
Run Code Online (Sandbox Code Playgroud)

操场

  • 如果我取消注释该行to_string_pretty(&z),编译就会失败,这很好。
  • let _z = ...即使没有该行,如果我取消注释,编译也会失败where T: Serialize。这很棒,因为它可以帮助库集成商在实际开始序列化之前发现他们正在使用struct X不可序列化的类型参数。

我尝试将其添加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,
}
Run Code Online (Sandbox Code Playgroud)

操场

有没有办法表达我正在寻找的这个约束?

She*_*ter 6

您需要使用来防止 Serde 尝试自动确定和实现#[serde(bound)]的界限: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
}
Run Code Online (Sandbox Code Playgroud)

也可以看看: