Serialising a HashMap with sorted keys


#1

Hi
I am trying to serialise a struct called ConsolidatedData which contains a HashMap for the values I want to serialise to json. The HashMap is index by a DateTime and the values are a vector of another struct called ElementData.

When serialising I want to sort the Hashmap values by the key.

I have with the help from online created a function to order the value as specified that with the serialize_with attribute.

The code is something like

#[derive(Debug, Clone, Serialize)]
struct ElementData {
    value: f64,
    tmp: [f64; 2] // Used for when we want min / max for diff
}

fn ordered_map<S>(map: &HashMap<DateTime<Utc>, Vec<ElementData>>, serializer: S) -> Result<S::Ok, S::Error>
where
    S: Serializer,
{
    let ordered: BTreeMap<DateTime<Utc>, Vec<ElementData>> = map.iter().collect();
    ordered.serialize(serializer)
}


#[derive(Serialize)]
struct ConsolidatedData {
    map: HashMap<i32, usize>,
    #[serde(serialize_with = "ordered_map")]
    values: HashMap<DateTime<Utc>, Vec<ElementData>>,  // Second element used for when we want min / max for diff
    number_of_sensors: usize
}

The trouble is I get errors like

error[E0599]: no method named serialize found for type std::collections::BTreeMap<chrono::DateTime<chrono::Utc>, std::vec::Vec<ElementData>> in the current scope
–> src/lib.rs:121:13
|
121 | ordered.serialize(serializer)
| ^^^^^^^^^
|
= note: the method serialize exists but the following trait bounds were not satisfied:
std::collections::BTreeMap<chrono::DateTime<chrono::Utc>, std::vec::Vec<ElementData>> : serde::Serialize

error[E0277]: the trait bound std::collections::BTreeMap<chrono::DateTime<chrono::Utc>, std::vec::Vec<ElementData>>: std::iter::FromIterator<(&chrono::DateTime<chrono::Utc>, &std::vec::Vec<ElementData>)> is not satisfied
–> src/lib.rs:120:73
|
120 | let ordered: BTreeMap<DateTime, Vec> = map.iter().collect();
| ^^^^^^^ a collection of type std::collections::BTreeMap<chrono::DateTime<chrono::Utc>, std::vec::Vec<ElementData>> cannot be built from an iterator over elements of type (&chrono::DateTime<chrono::Utc>, &std::vec::Vec<ElementData>)
|
= help: the trait std::iter::FromIterator<(&chrono::DateTime<chrono::Utc>, &std::vec::Vec<ElementData>)> is not implemented for std::collections::BTreeMap<chrono::DateTime<chrono::Utc>, std::vec::Vec<ElementData>>

What do I need to do here. Having trouble understanding the error.

Thanks


#2

map.iter() will give you references to the keys and values in the map - you can’t collect that into a BTreeMap of owned data (nor do you want to here). Try to let type inference do the typing for you: let ordered: BTreeMap<_,_> = ...


#3

When doing

let ordered: BTreeMap<_,_> = map.iter().collect();

I get the same general error of

error[E0599]: no method named serialize found for type std::collections::BTreeMap<&chrono::DateTime<chrono::Utc>, &std::vec::Vec<ElementData>> in the current scope
–> src/lib.rs:121:13
|
121 | ordered.serialize(serializer)
| ^^^^^^^^^
|
= note: the method serialize exists but the following trait bounds were not satisfied:
std::collections::BTreeMap<&chrono::DateTime<chrono::Utc>, &std::vec::Vec<ElementData>> : serde::Serialize


#4

You’re closer :slight_smile:. It looks like chrono has serde support behind a feature; try adding to your Cargo.toml:

[dependencies]
chrono = { version = "0.4", features = ["serde"] }

#5

Ah yes. I have that but it was in my parent cargo project. I added to my cargo lib prokect and it worked. Thanks.