#Serde deserielize into HashMap

5 messages · Page 1 of 1 (latest)

upbeat skiff
#

Hello,

I'm trying to deserialize something like this :

  "properties":[
    {
      "name":"Collision", 
      "type":"bool", 
      "value":true
    }
  ],

into :

  properties: HashMap<String, PropertyJson>,

[...]

#[derive(Deserialize, Debug)]
#[serde(tag = "type", rename_all = "lowercase")]
pub enum PropertyJson {
    Bool(bool),
}

Where each String in the HashMap<String, PropertyJson> correspond to the name of the property

quick kettle
#

i think this needs a custom Deserialize impl

timber crater
#

This is partially supported by serde, as far as I can tell.

If it weren't for the name field, I'd say the objects in that array fit an internally tagged enum: https://serde.rs/enum-representations.html#internally-tagged

#[derive(Deserialize)]
#[serde(tag = "type")]
enum Property {
  Bool { value: bool }
}
```However, there _is_ a `name` field, which isn't part of the enum. You can lift that one to an external struct using `flatten`:
```rs
#[derive(Deserialize)]
#[serde(tag = "type")]
#[serde(rename_all = "camelCase")]
enum PropertyValue {
  Bool { value: bool }
}
#[derive(Deserialize)]
struct Property {
    name: String,  
    #[serde(flatten)]
    value: PropertyValue,
}
```Unfortunately, I'm not aware of any way to tell serde "collect the fields of the objects in this json array into a hashmap, using one of the objects' fields' as the name"

So, now you have two options:
 - (difficult, maximally efficient) Write a `struct PropertyMap(HashMap<String, PropertyValue>);`. Manually implement `Deserialize` on that, probably taking inspiration from <https://serde.rs/stream-array.html>)
 - (easy, but a bit less efficient): Deserialize into a `Vec<Property>` as described above, then manually convert from that to `HashMap<String, PropertyValue>`
quick kettle
#

in both cases make sure you handle edge cases like duplicate names for example