How can I use serde json on a json object with variable key names

Viewed 2233

I am aware of the JSON value which can be used for unknown JSON.

What I have is a mostly structured JSON object like this:

{
    "error": [],
    "result": {
        "NAME_X": {
            "prop_one": "something",
            "prop_two": "something",
            "decimals": 1,
            "more_decimals": 2
        },
        "NAME_A": {
            "prop_one": "test",
            "prop_two": "sdfsdf",
            "decimals": 2,
            "more_decimals": 5
        },
        "ARBITRARY": {
            "prop_one": "something else",
            "prop_two": "blah",
            "decimals": 3,
            "more_decimals": 6
        }
}

So the inside object with fields prop_one, prop_two, decimals and more_decimals has a clear structure, but the outer name field/key (NAME_X, NAME_A, ARBITRARY) is unknown in advance.

What is the most straight forward way to parse this so I can use strongly typed variables/deserialization on the inner structure? I also still need to capture those unknown name fields.

1 Answers

You can deserialize into a map whose keys will be strings ("NAME_X", etc.):

use std::collections::HashMap;
use serde::Deserialize;
use serde_json::Result;

#[derive(Debug, Deserialize)]
struct InThing {
    prop_one: String,
    prop_two: String,
    decimals: u16,
    more_decimals: i32,
}
#[derive(Debug, Deserialize)]
struct OutThing {
    error: Vec<u8>,
    result: HashMap<String, InThing>,
}

fn main() {
    let data = r#"
        {
            "error": [],
            "result": {
                "NAME_X": {
                    "prop_one": "something",
                    "prop_two": "something",
                    "decimals": 1,
                    "more_decimals": 2
                },
                "NAME_A": {
                    "prop_one": "test",
                    "prop_two": "sdfsdf",
                    "decimals": 2,
                    "more_decimals": 5
                },
                "ARBITRARY": {
                    "prop_one": "something else",
                    "prop_two": "blah",
                    "decimals": 3,
                    "more_decimals": 6
                }
            }
        }
        "#;
    let thing: OutThing = serde_json::from_str(data).unwrap(); 
    dbg!(thing);
}

playground

Related