I’m looking for a better solution for deserializing nested JSON object like this
{"name":"John Doe","age":43,"address":"{"street":"10 Downing Street","city":"London"}"}
Using this code I do the job
use serde_derive::{Deserialize, Serialize};use serde_json::{Result, Value};
#[derive(Serialize, Deserialize)]
struct Person{
name: String,
address: Value
}
#[derive(Debug, Serialize, Deserialize)]
struct Address{
street: String,
city: String
}
impl From<Person> for Address{
fn from(p: Person) -> Self {
let str_val: String = serde_json::from_value(p.address).unwrap();
let ad: Self = serde_json::from_str(&str_val).unwrap();
ad
}
}
fn main() -> Result<()> {
let data = r#"{"name":"John Doe","age":43,"address":"{"street":"10 Downing Street","city":"London"}"}"#;
let p: Person = serde_json::from_str(data).unwrap();
println!("{:?}", Address::from(p));
Ok(())
}
But It seems to me that may be a better way to do it. Any suggestion?
2
Answers
Well
address: Value
does not seem useful, because heValue
in this case is aString
:eprintln!("{:?}", p.address);
will printSo you could just have
address: String
, and then deserialise from that directly:Alternatively you can use
deserialize_with
or create the deserializer for Person by hand, such that you can recursively invokeserde_json
in order to deserializeAddress
while deserializingPerson
.Probably the biggest advantage is you should not have to allocate a string for
Address
, you can deserialize from the borrowed data.Adding to @Masklinn’s answer, here is a working version based on
deserialize_with
:You can of course do it both ways: