Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Easy(er) way to deserialize a HashMap<&str, serde_json::Value> #1739

Closed
svanharmelen opened this issue Feb 12, 2020 · 8 comments
Closed

Easy(er) way to deserialize a HashMap<&str, serde_json::Value> #1739

svanharmelen opened this issue Feb 12, 2020 · 8 comments

Comments

@svanharmelen
Copy link

I know there is a serde_json::Map which has String keys, but I would really like to use something like this:

let mut data: HashMap<&str, serde_json::Value> = serde_json::from_str(content).unwrap();
// do custom stuff
let v: MyStruct = serde_json::from_value(serde_json::to_value(data).unwrap()).unwrap();

This works, but it would be nice if there is a way to do this without the additional to_value. Is that possible? Thanks!

@dtolnay
Copy link
Member

dtolnay commented Feb 12, 2020

The IntoDeserializer trait and the implementations of it in serde::de::value provide a way to deserialize directly from a map without the to_value conversion or allocations.

use serde::de::value::MapDeserializer;
use serde::Deserialize;
use serde_json::Value;
use std::collections::HashMap;

#[derive(Deserialize, Debug)]
struct MyStruct {
    a: usize,
    b: usize,
}

fn main() {
    let content = "{\"a\":1}";
    let mut data: HashMap<&str, Value> = serde_json::from_str(content).unwrap();
    data.insert("b", Value::from(2));
    let v = MyStruct::deserialize(MapDeserializer::new(data.into_iter())).unwrap();
    println!("{:#?}", v);
}

@svanharmelen
Copy link
Author

Super nice @dtolnay! Exactly the kind of solution I was hoping for 👍 Thanks!

@svanharmelen
Copy link
Author

svanharmelen commented Feb 13, 2020

Hmm... I actually have the same issue/question for doing this the other way around.

So serialize a struct into a HashMap. Again I can do this in two stages (first using to_value and then using from_value to get a HashMap, but I guess/hope there is be a better way to achieve this?

Additionally, if I do take the above two-step approach, I cannot use a HashMap<&str, Value> without getting lifetime errors which requires me to use a HashMap<String, Value> instead.

If doing this more elegant (in one go) isn;t possible, that it would be great to know how I can keep using &str keys instead of String keys.

Thanks!

@svanharmelen svanharmelen reopened this Feb 13, 2020
@svanharmelen
Copy link
Author

svanharmelen commented Feb 13, 2020

Hmm...Maybe a better solution for my problem/challenge is something along the lines of #1470

Asked an addition question there about that approach so if that works out this one can be closed...

@svanharmelen
Copy link
Author

Guess I'll close this issue as I don't expect any updates anymore...

@norbertkeri
Copy link

@dtolnay I can't seem to get your example to work with serde_yaml (but it works fine with json). Am I doing something wrong, or is this just a feature that is not yet implemented?

error[E0277]: the trait bound `serde_yaml::value::Value: _::_serde::de::IntoDeserializer<'_, _>` is not satisfied
  --> src/main.rs:16:35
   |
16 |     let v = MyStruct::deserialize(MapDeserializer::new(data.into_iter())).unwrap();
   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `_::_serde::de::IntoDeserializer<'_, _>` is not implemented for `serde_yaml::value::Value`
   |
   = note: required because of the requirements on the impl of `_::_serde::Deserializer<'_>` for `_::_serde::de::value::MapDeserializer<'_, std::collections::hash_map::IntoIter<&str, serde_yaml::value::Value>, _>`
   = note: required by `_::_serde::Deserialize::deserialize`

error: aborting due to previous error

@dtolnay
Copy link
Member

dtolnay commented Jul 30, 2020

@norbertkeri serde_yaml does not implement this but I filed dtolnay/serde-yaml#169 to follow up.

@norbertkeri
Copy link

Thanks!

@serde-rs serde-rs locked and limited conversation to collaborators Jun 29, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Development

No branches or pull requests

3 participants