简体   繁体   English

将 Rust 结构的泛型参数限制为反序列化

[英]Constraining generic parameter of Rust struct to be Deserialize

I would like to limit a (de)serializable struct to have a generic parameter that is also deserializable.我想限制(反)可序列化的结构具有一个也是可反序列化的泛型参数。 The derive macro Deserialize does not require me to add this constraint, which is nice, but I would like the integration code to get compilation errors even if they never try to deserialize the struct defined in the library.派生宏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 操场

  • The compilation fails if I uncomment the line with to_string_pretty(&z) , which is good.如果我用to_string_pretty(&z)取消注释该行,编译会失败,这很好。
  • Even without that line, the compilation fails on the let _z = ... line if I uncomment where T: Serialize .即使没有该行,如果我取消注释where T: Serialize ,编译也会在let _z = ...行上失败。 This is great, because it helps the library integrators to spot they are using struct X with a non-serializable type parameter even before they actually start serializing it.这很棒,因为它可以帮助库集成商在实际开始序列化之前发现他们正在使用具有不可序列化类型参数的struct X

I have tried to add where for<'a> T: serde::de::Deserialize<'a> as a constraint to struct X<T> , but that breaks the build even without anything using 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,
}

playground 操场

Is there a way to phrase this constraint I am looking for?有没有办法表达我正在寻找的这个约束?

You need to use #[serde(bound)] to prevent Serde from attempting to automatically determine the bounds on the Deserialize and Serialize implementations:您需要使用#[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
}

See also:也可以看看:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM