简体   繁体   English

带有反序列化和通用生命周期的 serde_json function

[英]serde_json with deserialize and lifetimes for generic function

Having issues with lifetimes and serde::deserialize.生命周期和 serde::deserialize 有问题。 Tried reading the error message and tried implementing Deserialize, but then I got an error that I need to implement Deserialize.尝试阅读错误消息并尝试实施反序列化,但随后出现错误,我需要实施反序列化。
Without lifetimes, it works没有生命周期,它可以工作

use serde::{ Deserialize, Serialize, de::DeserializeOwned};
use std::error::Error;
use std::io::{BufReader};
use std::{ fmt::Debug};
use std::{fs::File};

#[derive(Clone, Debug, Serialize, Deserialize)]
struct User<'a> {
    name: &'a str,
}

fn main(){
    let b: User = read_object("user_1.json").unwrap();
}


fn read_object<T>(path: &str) -> Result<T, Box<dyn Error>>
where
    T: DeserializeOwned + Debug,
{
    let f = File::open(&path)?;
    let reader = BufReader::new(f);

    let t: T = serde_json::from_reader(reader)?;

    Ok(t)
}

Error:错误:

   error: implementation of `Deserialize` is not general enough
  --> src/main.rs:13:19
   |
13 |     let b: User = read_object("user_1.json").unwrap();
   |                   ^^^^^^^^^^^ implementation of `Deserialize` is not general enough
   |
   = note: `User<'_>` must implement `Deserialize<'0>`, for any lifetime `'0`...
   = note: ...but `User<'_>` actually implements `Deserialize<'1>`, for some specific lifetime `'1`

This code cannot work.此代码无法运行。

The Deserialize<'de> trait has a lifetime associated with it to support zero-copy deserialization . Deserialize<'de>特性具有与之关联的生命周期以支持零拷贝反序列化 Essentially allows deserialized types to reference data directly from the source.本质上允许反序列化类型直接从源引用数据。 See Understanding deserializer lifetimes .请参阅了解解串器生命周期

When you have当你有

#[derive(Deserialize)]
struct User<'a> {
    name: &'a str,
}

The User will have the lifetime 'a linked to the deserialization source. User的生命周期'a将链接到反序列化源。 And name will be a reference to the string value within that source. name将是对该源中字符串值的引用。

On the flip-side, the DeserializeOwned trait does not support zero-copy deserialization.另一方面, DeserializeOwned特性不支持零拷贝反序列化。 The deserialized type must not have lifetimes associated with the Deserializer .反序列化类型不得具有与Deserializer关联的生命周期。 The "owned" means it doesn't borrow from anything. “拥有”意味着它不借用任何东西。 The cryptic error you get is due to the way DeserializeOwned is defined, it'll be implemented for any type that implements Deserialize for any lifetime, which will exclude types expecting a particular lifetime.您得到的神秘错误是由于DeserializeOwned的定义方式,它将针对任何生命周期实现Deserialize的任何类型实现,这将排除期望特定生命周期的类型。 This bound is used when lifetimes are unecessary or impossible to guarantee.当生命周期是不必要的或不可能保证时使用这个界限。

serde_json::from_reader is one of those cases. serde_json::from_reader就是其中一种情况。 It only deserializes JSON from sources based on the Read trait.它仅根据Read特征从源中反序列化 JSON。 However, the Read trait makes no guarantees that any read data is referenceable after the fact.然而, Read trait 不保证任何读取的数据在事后都是可引用的。 And thus from_reader dictates that T: DeserializeOwned to avoid that problem.因此from_reader指示T: DeserializeOwned以避免该问题。

To take advantage of zero-copy deserialization, you'd need to use from_slice or from_str :要利用零拷贝反序列化,您需要使用from_slicefrom_str

let data = std::fs::read_to_string(path)?;
let user: User = serde_json::from_str(&data)?;

However, even if you do that, the data being referenced is local only to the read_object function. All data retrieved from the file is destroyed at the end of the function, and would leave user.name invalid if it were returned.然而,即使你这样做,被引用的数据也只是read_object function 的本地数据。从文件中检索到的所有数据都在 function 结束时被销毁,并且如果返回user.name将无效。 The compiler would reject it ( playground ).编译器会拒绝它( 游乐场)。

Without lifetimes, it works没有生命周期,它可以工作

And that's what I suggest you do;这就是我建议你做的; just use struct User { name: String } .只需使用struct User { name: String } I would advise against trying to use zero-cost deserialization from JSON strings at all because of escape sequences .由于转义序列,我建议不要尝试使用 JSON 字符串的零成本反序列化。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM