当函数返回一个serde Deserialize类型时,如何解决生命周期错误?

28
我使用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 {

所以我添加了lifetime:
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 1.18.0-nightly (452bf0852 2017-04-19)。我只了解Rust生命周期的基础知识,所以我对trait Deserialize中的'de'感到非常困惑。
在这样的函数中,我该如何解决生命周期错误?
2个回答

21

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


20

本部分介绍了Serde网站中Deserialize边界的详细信息。


有两种主要的方式来编写 Deserialize 特质边界,无论是在 impl 块、函数或任何其他地方。

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

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

  • <T> where T: DeserializeOwned

    这意味着 "T可以从任何生命周期反序列化。" 被调用者决定生命周期。通常情况下,这是因为被反序列化的数据将在函数返回之前被丢弃,所以T不能从它借用。例如,一个函数接受base64编码的数据作为输入,对其进行解码,反序列化类型为T的值,然后丢弃base64解码结果的函数。另一个常见的使用这个约束的例子是从IO流反序列化的函数,例如serde_json::from_reader

    更技术地说,DeserializeOwned特质等同于高阶特质限定for<'de> Deserialize<'de>。唯一的区别是DeserializeOwned更直观易读。它意味着T拥有所有被反序列化的数据。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接