代码之家  ›  专栏  ›  技术社区  ›  EatonWu

在使用泛型和生存期的同时,使用serde/serde_JSON对JSON序列化/反序列化进行Rust?

  •  1
  • EatonWu  · 技术社区  · 1 年前

    这个问题与 serde_json with deserialize and lifetimes for generic function 因为from_slice和from_str都不起作用,而且错误消息也不同。

    这个问题与 serde/rust deserialize JSON into Hashmap ,因为他们不会遇到特质界限的问题。

    这个问题与 Lifetime error with Serde in a Generic Function 因为当我将Deserialize更改为DeserializeOwned或实现更高级别的特征边界时,我仍然会遇到这个问题。


    我的目标很简单:围绕一个范围映射(crate:rangemap)创建一个结构包装器(它已经可以使用serde1功能进行序列化),允许我将数据保存到一个文件中。

    我还希望它在结构被丢弃时调用save函数(通过执行Drop) 为了简洁起见,以下代码缺少一些明显的检查(文件位置是否有效)。

    结构定义:

        use serde::{Deserialize, Serialize};
        use serde_json;
        use rangemap::RangeMap;
        use serde::de::DeserializeOwned;
        #[derive(Debug, Clone, Serialize, Deserialize)]
        pub struct RangeDataStorage<K, V> 
            where
                K: Ord + Clone + Eq + Debug + Default + Serialize + Deserialize,
                V: Default + Serialize + Debug + Eq + Clone + Deserialize {
            range_map: RangeMap<K, V>,
        }
    

    我已经对structimpls进行了几次迭代:

    结构impl:

        impl<K, V> RangeDataStorage<K, V>
            where
                K: Ord + Clone + Eq + Debug + Default + Serialize + Deserialize,
                V: Default + Serialize + Debug + Eq + Clone + Deserialize{
            pub fn new(location: Option<String>) -> Result<RangeDataStorage<K, V>, Box<dyn Error>> {
                if location.is_some() {
                    // load from file
                    let location = location.unwrap();
                    let data = std::fs::read_to_string(location)?;
                    let data: RangeDataStorage<K, V> = serde_json::from_str(&data)?;
                    let data = data.clone(); // does not fix problem
                    return Ok(data);
                }
                Ok(
                    RangeDataStorage {
                        range_map: RangeMap::new(),
                    }
                )
            }
        
            pub fn insert(&mut self, key_start: K, key_end: K, value: V) {
                let range = Range {
                    start: key_start,
                    end: key_end,
                };
                self.range_map.insert(range, value);
            }
        
            pub fn save(&mut self, location: String) {
                let file = std::fs::File::create(location).unwrap();
                let writer = std::io::BufWriter::new(file);
                let res = serde_json::to_writer(writer, self);
                match res {
                    Ok(_) => {},
                    Err(e) => { println!("Error while saving file : {:?}", e); }
                }
            }
        
            pub fn get(&self, key: K) -> Option<&V> {
                self.range_map.get(&key)
            }
        }
    

    货物投诉:

    error[E0106]: missing lifetime specifier
      --> src\main.rs:13:61
       |
    13 |         K: Ord + Clone + Eq + Debug + Default + Serialize + Deserialize,
       |                                                             ^^^^^^^^^^^ expected named lifetime parameter
       |
       = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
    help: consider making the bound lifetime-generic with a new `'a` lifetime
       |
    13 |         K: Ord + Clone + Eq + Debug + Default + Serialize + for<'a> Deserialize<'a>,
       |                                                             +++++++            ++++
    help: consider making the bound lifetime-generic with a new `'a` lifetime
       |
    13 |         for<'a> K: Ord + Clone + Eq + Debug + Default + Serialize + Deserialize<'a>,
       |         +++++++                                                                ++++
    help: consider introducing a named lifetime parameter
       |
    11 ~ pub struct RangeDataStorage<'a, K, V>
    12 |     where
    13 ~         K: Ord + Clone + Eq + Debug + Default + Serialize + Deserialize<'a>,
    

    在这个迭代中,cargo抱怨缺少生存期说明符。我仍然不确定为什么这是个问题。 我已经阅读了serde反序列化程序的终身文章:

    https://serde.rs/lifetimes.html

    我不确定我错过了什么。我认为生存期是必要的,因为serde专注于零副本反序列化(反序列化的对象指的是反序列化器借用的数据,因此借用检查器需要确保借用的数据不会超出范围,从而延长生存期)。

    但是,克隆数据应该可以解决这个问题,对吧?事实并非如此。

    Cargo建议为缺失的寿命说明符添加更高的等级特征边界;前面提到的serde文章提到,更高级别的特征边界相当于使用DeserializeOwned(我两者都尝试过):

    添加更高等级的特征边界:

        #[derive(Debug, Clone, Serialize, Deserialize)]
        pub struct RangeDataStorage<K, V>
            where
                K: Ord + Clone + Eq + Debug + Default + Serialize + for<'a>Deserialize<'a>,
                V: Default + Serialize + Debug + Eq + Clone + for<'a>Deserialize<'a> {
            range_map: RangeMap<K, V>,
        }
        
        impl<K, V> RangeDataStorage<K, V>
            where
                K: Ord + Clone + Eq + Debug + Default + Serialize + for<'a>Deserialize<'a>,
                V: Default + Serialize + Debug + Eq + Clone + for<'a>Deserialize<'a>{
    

    新问题,是否需要键入注释?哪里怎样

        error[E0283]: type annotations needed: cannot satisfy `K: Deserialize<'_>`
          --> src\main.rs:11:12
           |
        11 | pub struct RangeDataStorage<K, V>
           |            ^^^^^^^^^^^^^^^^^^^^^^
           |
        note: multiple `impl`s or `where` clauses satisfying `K: Deserialize<'_>` found
          --> src\main.rs:10:35
           |
        10 | #[derive(Debug, Clone, Serialize, Deserialize)]
           |                                   ^^^^^^^^^^^
        ...
        13 |         K: Ord + Clone + Eq + Debug + Default + Serialize + for<'a>Deserialize<'a>,
           |                                                             ^^^^^^^^^^^^^^^^^^^^^^
        note: required for `RangeDataStorage<K, V>` to implement `Deserialize<'de>`
          --> src\main.rs:10:35
           |
        10 | #[derive(Debug, Clone, Serialize, Deserialize)]
           |                                   ^^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
        11 | pub struct RangeDataStorage<K, V>
           |            ^^^^^^^^^^^^^^^^^^^^^^
           = note: this error originates in the derive macro `Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info)
    

    当用DeserializeOwned替换较高级别的特征边界时,也会出现同样的错误:

        #[derive(Debug, Clone, Serialize, Deserialize)]
        pub struct RangeDataStorage<K, V>
            where
                K: Ord + Clone + Eq + Debug + Default + Serialize + DeserializeOwned,
                V: Default + Serialize + Debug + Eq + Clone + DeserializeOwned {
            range_map: RangeMap<K, V>,
        }
        
        impl<K, V> RangeDataStorage<K, V>
            where
                K: Ord + Clone + Eq + Debug + Default + Serialize + DeserializeOwned,
                V: Default + Serialize + Debug + Eq + Clone + DeserializeOwned{
    
        error[E0283]: type annotations needed: cannot satisfy `K: Deserialize<'_>`
          --> src\main.rs:11:12
           |
        11 | pub struct RangeDataStorage<K, V>
           |            ^^^^^^^^^^^^^^^^^^^^^^
           |
        note: multiple `impl`s or `where` clauses satisfying `K: Deserialize<'_>` found
          --> src\main.rs:10:35
           |
        10 | #[derive(Debug, Clone, Serialize, Deserialize)]
           |                                   ^^^^^^^^^^^
        ...
        13 |         K: Ord + Clone + Eq + Debug + Default + Serialize + DeserializeOwned,
           |                                                             ^^^^^^^^^^^^^^^^
        note: required for `RangeDataStorage<K, V>` to implement `Deserialize<'de>`
          --> src\main.rs:10:35
           |
        10 | #[derive(Debug, Clone, Serialize, Deserialize)]
           |                                   ^^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
        11 | pub struct RangeDataStorage<K, V>
           |            ^^^^^^^^^^^^^^^^^^^^^^
           = note: this error originates in the derive macro `Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info)
    

    对这个问题进行简短的谷歌搜索会得到以下结果: https://github.com/serde-rs/serde/issues/2418

    这对我没有帮助,因为删除结构上的where子句也会给我带来问题,因为货物现在抱怨类型K和V需要由Ord、Clone、Eq(反序列化所必需的)来约束。

    在这一点上,我迷失了方向,我真的找不到任何关于相对简单的任务的信息,而且我甚至还没有实现Drop函数。

    谢谢你能提供的任何帮助。

    1 回复  |  直到 1 年前
        1
  •  1
  •   cdhowie    1 年前

    这个 Deserialize 派生宏无法计算实现所需的实际边界 反序列化 用于您的结构。结果是从编译器中得到相当不透明的错误消息。

    要解决此问题,您可以 write the Deserialize implementation bounds yourself 而不是让塞德去想办法。这也意味着你可以放弃 where 完全与您的结构绑定;您实际上不需要任何这些边界来定义结构,而且通常 you shouldn't bound the generic parameters of a type unless it's absolutely required to define the type .

    结果如下所示:

    #[derive(Debug, Clone, Serialize, Deserialize)]
    pub struct RangeDataStorage<K, V> {
        #[serde(bound(deserialize = r"
            K: Ord + Clone + Deserialize<'de>,
            V: Eq + Clone + Deserialize<'de>,
        "))]
        range_map: RangeMap<K, V>,
    }
    

    您可以通过从空边界开始并添加编译器建议的内容直到编译,或者通过从复制边界来派生这些边界 RangeMap 's Deserialize implementation .

    推荐文章