如何将受特征限制的类型传递给 Serde 的 deserialize_with?
How do I pass a type bounded by a trait to Serde's deserialize_with?
满足MyTrait
的类型应该传递给deserialize_with
指定的deserialize_data
。这是我的 sample code:
use serde::{Deserialize, Deserializer}; // 1.0.117
use serde_json; // 1.0.59
type Item = Result<String, Box<dyn std::error::Error + Send + Sync>>;
pub trait MyTrait {
fn method(ind: &str) -> Item;
}
#[derive(Deserialize)]
pub struct S<T>
where
T: MyTrait + ?Sized, // intend to pass a type T satisfying `MyTrait` to function `deserialize_data`,
{
#[serde(deserialize_with = "deserialize_data")]
//#[serde(bound( deserialize = "T: MyTrait, for<'de2> T: Deserialize<'de2>" ))]
pub data: String,
}
fn deserialize_data<'de, D, T>(d: D) -> Result<String, D::Error>
where
D: Deserializer<'de>,
{
let ind = <&str>::deserialize(d).unwrap();
match T::method(ind) {
Ok(data) => Ok(data),
Err(e) => Err(serde::de::Error::custom(format_args!("invalid type."))),
}
}
struct A;
impl MyTrait for A {
fn method(_ind: &str) -> Item {
// to make it simple, return constant
Ok("method".to_string())
}
}
fn main() {
let s = r#"{"data": "string"}"#;
let ob: S<A> = serde_json::from_str(s).unwrap();
}
编译器抱怨:
error[E0392]: parameter `T` is never used
--> src/main.rs:10:14
|
10 | pub struct S<T>
| ^ unused parameter
|
= help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
我确实使用 T
,而 PhantomData
帮助不大。
一种明显的方法可能是使用 struct A
及其实现的方法作为 crate 或其他东西,然后导入它们。不幸的是,这不适用于我的情况,所以我试图将结构类型传递给 deserialize_data
并实现它。
要编译代码,您需要:
- 在
struct S<T>
中使用 T
,例如 PhantomData
。
- 使用 turbofish 运算符
::<>
. 显式将 T
传递给 deserialize_data
- 为
deserialize_data()
中的T
泛型添加适当的trait bounds,例如MyTrait
.
例如(playground):
#[derive(Deserialize)]
pub struct S<T>
where
T: MyTrait + ?Sized,
{
#[serde(deserialize_with = "deserialize_data::<_, T>")]
pub data: String,
marker: std::marker::PhantomData<T>,
}
fn deserialize_data<'de, D, T>(d: D) -> Result<String, D::Error>
where
D: Deserializer<'de>,
T: MyTrait + ?Sized,
{
// ...
}
满足MyTrait
的类型应该传递给deserialize_with
指定的deserialize_data
。这是我的 sample code:
use serde::{Deserialize, Deserializer}; // 1.0.117
use serde_json; // 1.0.59
type Item = Result<String, Box<dyn std::error::Error + Send + Sync>>;
pub trait MyTrait {
fn method(ind: &str) -> Item;
}
#[derive(Deserialize)]
pub struct S<T>
where
T: MyTrait + ?Sized, // intend to pass a type T satisfying `MyTrait` to function `deserialize_data`,
{
#[serde(deserialize_with = "deserialize_data")]
//#[serde(bound( deserialize = "T: MyTrait, for<'de2> T: Deserialize<'de2>" ))]
pub data: String,
}
fn deserialize_data<'de, D, T>(d: D) -> Result<String, D::Error>
where
D: Deserializer<'de>,
{
let ind = <&str>::deserialize(d).unwrap();
match T::method(ind) {
Ok(data) => Ok(data),
Err(e) => Err(serde::de::Error::custom(format_args!("invalid type."))),
}
}
struct A;
impl MyTrait for A {
fn method(_ind: &str) -> Item {
// to make it simple, return constant
Ok("method".to_string())
}
}
fn main() {
let s = r#"{"data": "string"}"#;
let ob: S<A> = serde_json::from_str(s).unwrap();
}
编译器抱怨:
error[E0392]: parameter `T` is never used
--> src/main.rs:10:14
|
10 | pub struct S<T>
| ^ unused parameter
|
= help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
我确实使用 T
,而 PhantomData
帮助不大。
一种明显的方法可能是使用 struct A
及其实现的方法作为 crate 或其他东西,然后导入它们。不幸的是,这不适用于我的情况,所以我试图将结构类型传递给 deserialize_data
并实现它。
要编译代码,您需要:
- 在
struct S<T>
中使用T
,例如PhantomData
。 - 使用 turbofish 运算符
::<>
. 显式将 - 为
deserialize_data()
中的T
泛型添加适当的trait bounds,例如MyTrait
.
T
传递给 deserialize_data
例如(playground):
#[derive(Deserialize)]
pub struct S<T>
where
T: MyTrait + ?Sized,
{
#[serde(deserialize_with = "deserialize_data::<_, T>")]
pub data: String,
marker: std::marker::PhantomData<T>,
}
fn deserialize_data<'de, D, T>(d: D) -> Result<String, D::Error>
where
D: Deserializer<'de>,
T: MyTrait + ?Sized,
{
// ...
}