将 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(())
}
- 如果我取消注释带有
to_string_pretty(&z)
的行,编译会失败,这很好。
- 即使没有该行,如果我取消注释
where T: Serialize
,编译也会在 let _z = ...
行失败。这很棒,因为它可以帮助库集成商发现他们正在使用 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,
}
有没有办法表达我正在寻找的这个限制条件?
您需要使用 #[serde(bound)]
来防止 Serde 尝试自动确定 Deserialize
和 Serialize
实现的边界:
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
我想将可(反)序列化结构限制为具有也可反序列化的通用参数。派生宏 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(())
}
- 如果我取消注释带有
to_string_pretty(&z)
的行,编译会失败,这很好。 - 即使没有该行,如果我取消注释
where T: Serialize
,编译也会在let _z = ...
行失败。这很棒,因为它可以帮助库集成商发现他们正在使用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,
}
有没有办法表达我正在寻找的这个限制条件?
您需要使用 #[serde(bound)]
来防止 Serde 尝试自动确定 Deserialize
和 Serialize
实现的边界:
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