手写的泛型类型边界
当为具有泛型类型参数的结构派生 Serialize
和 Deserialize
实现时,大多数时候 Serde 能够在没有程序员帮助的情况下推断出正确的特征边界 。它使用几种启发式方法来猜测右边界,但最重要的是,它将 T: Serialize
的一个界限放在每个类型参数 T
上,这是一个序列化字段的一部分,T: Deserialize
的界限是每个类型参数 T
,它是反序列化字段的一部分。与大多数启发式方法一样,这并不总是正确的,Serde 提供了一个逃生舱口,用程序员编写的一个替换自动生成的界限。
extern crate serde;
extern crate serde_json;
#[macro_use] extern crate serde_derive;
use serde::de::{self, Deserialize, Deserializer};
use std::fmt::Display;
use std::str::FromStr;
#[derive(Deserialize, Debug)]
struct Outer<'a, S, T: 'a + ?Sized> {
// When deriving the Deserialize impl, Serde would want to generate a bound
// `S: Deserialize` on the type of this field. But we are going to use the
// type's `FromStr` impl instead of its `Deserialize` impl by going through
// `deserialize_from_str`, so we override the automatically generated bound
// by the one required for `deserialize_from_str`.
#[serde(deserialize_with = "deserialize_from_str")]
#[serde(bound(deserialize = "S: FromStr, S::Err: Display"))]
s: S,
// Here Serde would want to generate a bound `T: Deserialize`. That is a
// stricter condition than is necessary. In fact, the `main` function below
// uses T=str which does not implement Deserialize. We override the
// automatically generated bound by a looser one.
#[serde(bound(deserialize = "Ptr<'a, T>: Deserialize"))]
ptr: Ptr<'a, T>,
}
/// Deserialize a type `S` by deserializing a string, then using the `FromStr`
/// impl of `S` to create the result. The generic type `S` is not required to
/// implement `Deserialize`.
fn deserialize_from_str<S, D>(deserializer: D) -> Result<S, D::Error>
where S: FromStr,
S::Err: Display,
D: Deserializer
{
let s: String = try!(Deserialize::deserialize(deserializer));
S::from_str(&s).map_err(|e| de::Error::custom(e.to_string()))
}
/// A pointer to `T` which may or may not own the data. When deserializing we
/// always want to produce owned data.
#[derive(Debug)]
enum Ptr<'a, T: 'a + ?Sized> {
Ref(&'a T),
Owned(Box<T>),
}
impl<'a, T: 'a + ?Sized> Deserialize for Ptr<'a, T>
where Box<T>: Deserialize
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer
{
let box_t = try!(Deserialize::deserialize(deserializer));
Ok(Ptr::Owned(box_t))
}
}
fn main() {
let j = r#"
{
"s": "1234567890",
"ptr": "owned"
}
"#;
let result: Outer<u64, str> = serde_json::from_str(j).unwrap();
// result = Outer { s: 1234567890, ptr: Owned("owned") }
println!("result = {:?}", result);
}