Search code examples
rustserde

Rust serde serialization to/from Vec into HashMap


I have a JSON collection that contains elements of a map that I would like to serialize back/forth to a list representation. This is the code I have written:

use serde::{de::DeserializeOwned, Deserialize, Serialize};
use std::{collections::HashMap, hash::Hash};

pub trait GetId<T>
{
    fn get_id(&self) -> &T;
}

/// Serializable collection
#[derive(Serialize, Deserialize, Default, Clone)]
#[serde(from="Vec<V>", into="Vec<V>")]
pub struct Collection<K, V>
where K: Eq + Hash + Clone,
      V: Serialize + DeserializeOwned + GetId<K> + Clone,
{
    data: HashMap<K, V>,
}

impl<K, V> Collection<K, V>
where K: Eq + Hash + Clone,
      V: Serialize + DeserializeOwned + GetId<K> + Clone,
{
    pub fn new() -> Self {
        Collection {
            data: HashMap::new(),
        }
    }

    pub fn insert(&mut self, item: V) -> Option<V> {
        let id = item.get_id().to_owned();
        self.data.insert(id, item)
    }
}

impl<K, V> From<Vec<V>> for Collection<K, V>
where K: Eq + Hash + Clone,
      V: Serialize + DeserializeOwned + GetId<K> + Clone,
{
    fn from(value: Vec<V>) -> Self {
        let mut obj: Collection<K, V> = Collection::new();
        value.into_iter().for_each(|v| { obj.insert(v); });
        obj
    }
}

impl<K, V> Into<Vec<V>> for Collection<K, V>
where K: Eq + Hash + Clone,
      V: Serialize + DeserializeOwned + GetId<K> + Clone,
{
    fn into(self) -> Vec<V> {
        Vec::from_iter(self.data.into_values())
    }
}

I use the From<Vec<V>> implementation and the GetKey<K> trait to insert all the elements of the serialized Vec<V> into the HashMap<K, V>.

I'm having issues with the lifetimes here however, and am getting errors such as the below:

error[E0283]: type annotations needed: cannot satisfy `V: Deserialize<'_>`
  --> src\idls\collection.rs:14:12
   |
14 | pub struct Collection<K, V>
   |            ^^^^^^^^^^^^^^^^
   |
note: multiple `impl`s or `where` clauses satisfying `V: Deserialize<'_>` found
  --> src\idls\collection.rs:12:21
   |
12 | #[derive(Serialize, Deserialize, Default, Clone)]
   |                     ^^^^^^^^^^^
...
17 |     V: Serialize + DeserializeOwned + GetId<K> + Clone,
   |                    ^^^^^^^^^^^^^^^^
note: required for `Collection<K, V>` to implement `Deserialize<'de>`
  --> src\idls\collection.rs:12:21
   |
12 | #[derive(Serialize, Deserialize, Default, Clone)]
   |                     ^^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
13 | #[serde(from="Vec<V>", into="Vec<V>")]
14 | pub struct Collection<K, V>
   |            ^^^^^^^^^^^^^^^^
   = note: this error originates in the derive macro `Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info)


I'm not familiar enough with Rust to understand what I'm doing wrong here. I read thru the Deserializer lifetimes docs that Serde provided, but I don't quite understand why these generics don't seem to be working. I've tried swapping DeserializeOwned with for<'a> Deserialize<'a>, but I don't believe that's correct for my use case, and also it doesn't work.


Solution

  • Deriving Serialize and Deserialize will automatically add the necessary trait bounds to generic parameters, so you should not write them yourself. So, just remove Serialize + DeserializeOwned from the trait bounds on V.