Serialize and deserialize HashMap to JSON in Rust

HashMap serialize deserialize serde_json serde to_string from_str JSON assert_eq!

In most of the other articles about JSON and Rust we deal with data that can be represented by a struct where the keys are fixed and known up-front.

There are, however, cases when the keys can be arbitrary values of some type. E.g. arbitrary strings. For example if we want to count how many times a word appears in a text, the best representation might be a HashMap where we won't know up-front which words are in a text and thus won't know up-front what will be the keys.

So in this example we took a HashMap that with key-value pairs in it mapping Strings to numbers and we serialized the HashMap using serde_json::to_string to a JSON string:

let json_string = serde_json::to_string(&data_before).unwrap();

Then deserialized it using serde_json::from_str back to a HashMap with the appropriate type definition.

let data_after: HashMap<String, u32> = serde_json::from_str(&json_string).unwrap();

Actually I included two ways to deserialize, once by declaring the type of the new variable and once by using the Turbofish 🐠 operator.

let data_turbofish = serde_json::from_str::<HashMap<String, u32>>(&json_string).unwrap();

Use whichever makes more sense to you.

After both deserialization we used the assert_eq! macro to compare the resulting data structure to the original one.

The dependencies in Cargo.toml

We need serde_json for this.

examples/hash-to-json/Cargo.toml

[package]
name = "hash-to-json"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
serde_json = "1.0"

The code

examples/hash-to-json/src/main.rs

use std::collections::HashMap;

fn main() {
    let mut data_before = HashMap::new();
    data_before.insert("foo".to_string(), 23);
    data_before.insert("bar".to_string(), 42);
    println!("{:?}", data_before);

    // serialize
    let json_string = serde_json::to_string(&data_before).unwrap();
    println!("{}", json_string);

    // deserialize
    let data_after: HashMap<String, u32> = serde_json::from_str(&json_string).unwrap();
    println!("{:?}", data_after);
    assert_eq!(data_before, data_after);

    // doing the same using Turbofish
    let data_turbofish = serde_json::from_str::<HashMap<String, u32>>(&json_string).unwrap();
    println!("{:?}", data_turbofish);
    assert_eq!(data_before, data_turbofish);

}

Running the example

cargo run

Will print:

{"bar": 42, "foo": 23}
{"bar":42,"foo":23}
{"bar": 42, "foo": 23}
{"foo": 23, "bar": 42}

Related Pages

JSON and Rust
Command line multi-counter with storage in JSON file

Author

Gabor Szabo (szabgab)

Gabor Szabo, the author of the Rust Maven web site maintains several Open source projects in Rust and while he still feels he has tons of new things to learn about Rust he already offers training courses in Rust and still teaches Python, Perl, git, GitHub, GitLab, CI, and testing.

Gabor Szabo