22

我正在使用 serde 和 serde_json 1.0 来解码来自 base64 字符串的数据:

fn from_base64_str<T: Deserialize>(string: &str) -> T {
    let slice = decode_config(string, URL_SAFE).unwrap();     
    serde_json::from_slice(&slice).unwrap()
}

当我编译时,我得到了这个:

error[E0106]: missing lifetime specifier
 --> src/main.rs:6:23
  |
6 | fn from_base64_str<T: Deserialize>(string: &str) -> T {
  |                       ^^^^^^^^^^^ expected lifetime parameter

检查 serde 文档,Deserialize定义为:

pub trait Deserialize<'de>: Sized {

所以我添加了生命周期:

fn from_base64_str<'de, T: Deserialize<'de>>(string: &str) -> T {
    let slice = decode_config(string, URL_SAFE).unwrap();     
    serde_json::from_slice(&slice).unwrap()
}

然后编译器告诉我:

error: `slice` does not live long enough
  --> src/main.rs:11:29
   |
11 |     serde_json::from_slice(&slice).unwrap()
   |                             ^^^^^ does not live long enough
12 | }
   | - borrowed value only lives until here
   |
note: borrowed value must be valid for the lifetime 'de as defined on the body at 9:64...
  --> src/main.rs:9:65
   |
9  |   fn from_base64_str<'de, T: Deserialize<'de>>(string: &str) -> T {
   |  _________________________________________________________________^ starting here...
10 | |     let slice = decode_config(string, URL_SAFE).unwrap();
11 | |     serde_json::from_slice(&slice).unwrap()
12 | | }
   | |_^ ...ending here

我只知道 Rust 生命周期的基础知识,所以我对'dein非常困惑trait Deserialize

如何修复此类函数中的生命周期错误?我每晚使用 Rust 1.18.0 (452bf0852 2017-04-19)

4

2 回答 2

18

我从Serde 问题 891中找到了答案:我应该使用DeserializeOwned而不是Deserialize.

于 2017-04-22T03:36:11.067 回答
14

Serde 网站的这一部分Deserialize详细介绍了边界。


有两种主要的方法来编写Deserializetrait bound,无论是在 impl 块或函数上还是在其他任何地方。

  • <'de, T> where T: Deserialize<'de>

    这意味着“T 可以从某个生命周期中反序列化”。调用者可以决定那是什么生命周期。通常,当调用者还提供要反序列化的数据时使用,例如在类似serde_json::from_str. 在这种情况下,输入数据也必须具有生命周期'de,例如它可以是&'de str.

  • <T> where T: DeserializeOwned

    这意味着“T 可以从任何生命周期反序列化”。被调用者可以决定什么生命周期。通常这是因为要反序列化的数据将在函数返回之前被丢弃,因此不能允许 T 从中借用。例如,一个函数接受 base64 编码的数据作为输入,从 base64 解码,反序列化 T 类型的值,然后丢弃 base64 解码的结果。此绑定的另一个常见用途是从 IO 流反序列化的函数,例如serde_json::from_reader.

    说得更专业一点,DeserializeOwnedtrait 相当于更高级别的 trait bound for<'de> Deserialize<'de>。唯一的区别是DeserializeOwned阅读起来更直观。这意味着 T 拥有所有被反序列化的数据。

于 2017-04-22T20:38:48.150 回答