Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to (de)serialize a strongly typed JSON dictionary in Serde?

Tags:

json

rust

serde

I am writing a Rust application that handles JSON messages from a TypeScript client with a public interface. I have written some code using serde_derive and it works well, but I can't figure out how to implement dictionaries; e.g.:

{
  "foo" : { "data" : 42 },
  "bar" : { "data" : 1337 }
}

Here the keys are the strings "foo" and "bar" and the dictionary's values follow this schema:

use serde_derive;
use serde_json::Number;

#[derive(Serialize, Deserialize)]
struct DictionaryValue {
    data: Number,
}

I am looking to access the JSON data in this manner:

#[derive(Serialize, Deserialize)]
struct Dictionary {
    key: String,
    value: DictionaryValue,
}

How can I (de)serialize my JSON data into/from Dictionary using Serde?

like image 590
Filippo Costa Avatar asked Jan 02 '23 13:01

Filippo Costa


1 Answers

You have a logic error in your code. The structure in your JSON file describes an associative array but your Dictionary does not support multiple key-value-pairs. As Stargateur stated in the comments, you may use HashMap as Serde has Serialize and Deserialize implementations for HashMap.

Instead of using a single key-value-pair, you can rewrite your Dictionary as

type Dictionary = HashMap<String, DictionaryValue>;

and you can retrieve the data for example by

let dict: Dictionary = serde_json::from_str(json_string).unwrap();

If you now want to wrap everything in a Dictionary-struct it will look like this:

#[derive(Serialize, Deserialize)]
struct Dictionary {
    inner: HashMap<String, DictionaryValue>,
}

The problem is, that serde_json now expects

{
  "inner": {
    "foo" : { "data" : 42 },
    "bar" : { "data" : 1337 }
  }
}

To get rid of this, you can add the serde(flatten) attribute to Dictionary:

#[derive(Serialize, Deserialize, Debug)]
struct Dictionary {
    #[serde(flatten)]
    inner: HashMap<String, DictionaryValue>,
}

If HashMap or any BTreeMap from std does not fit your needs, you can also implement your Dictionary on your own. See the docs here and here for more details.

like image 72
Tim Diekmann Avatar answered Jan 05 '23 17:01

Tim Diekmann