Search code examples
serializationrustdeserializationserde

Why Error("trailing characters") when trying to deserialize a JSON file to a hashmap?


So basically, I'm trying to deserialize a JSON file into a hashmap<String,String> using the serde crate, but. The JSON file:

"
    [
        {
            "orchard_name": "Happy Apple",
            "tons": "5"
        },
        {
            "orchard_name": "Munch for Lunch",
            "tons": "2"
        }
    ]
    "

This is my structure:

#[derive(Serialize, Deserialize, Debug)]
struct OrangeFarm
{
    map : HashMap<String,String>
}

and this is where I try to do the deserialization:

let res = serde_json::from_str(_json);
if res.is_ok() {println!("Deserealization worked."); }
else { println!("it went wrong"); }
let mut deserializedFarm : OrangeFarm = res.unwrap();

For some reason, it works if I delete the second {}, but it doesn't if I let the second {} as I get this error "thread 'main' panicked at 'called Result::unwrap() on an Err value: Error("trailing characters" . Do you have any idea why this happens? Thank you!


Solution

  • For some reason, it works if I delete the second {}, but it doesn't if I let the second {}

    I have no idea what this means, but as far as I can see it never works: you're trying to deserialise an array of structures but you're deserialising to a structure. So the deserialisation logically fails. The code always panics, though in the initial case it also prints "it went wrong".

    Furthermore, your structure definition doesn't match the JSON so even if you try deserializing to a Vec<OrangeFarm> the call will fail: serde expects to find a map attribute, which is not present in the JSON. So you need to either fix your structure, or configure the serialisation / deserialisation scheme.

    Deserializing to a Vec<HashMap<String, String>> would work but I've no idea whether that is your intent.

    That aside:

    • Please provide minimal complete runnable reproduction cases using play.rust-lang.org when that is possible (which it is here) and use regular code blocks to show the case in the comment, these html snippet things obviously can't work for rust (especially when the code is not even complete) so they just take room and break syntax coloration
    • What little code there is is... odd. One would not normally check for is_ok/is_err then immediately unwrap, instead you'd use match or if let to cleanly do both at the same time and avoid the risk of desync, misunderstanding, etc... there are situations where unwrap.
    • Calling a variable you're actively using _json is abnormal, the _ prefix is intended for variables you want to capture but don't want to use (it suppresses the unused_variables lint without dropping the value immediately, which would be the effect of a lone _).