Search code examples
jsonserializationrustserderust-rocket

Deserialization of JSON reponse keeps quotation marks in Strings


I am querying a Google API using reqwest:

let request_url = format!(
    "https://maps.googleapis.com/maps/api/place/findplacefromtext/json?input=*\
     &inputtype=textquery\
     &fields=formatted_address,name,place_id,types\
     &locationbias=circle:50@{},{}\
     &key=my-secret-key",
    lat, lng
);

let mut response = reqwest::get(&request_url).expect("pffff");

let gr: GoogleResponse = response.json::<GoogleResponse>().expect("geeez");

The GoogleResponse struct is defined as

#[derive(Debug, Serialize, Deserialize)]
pub struct DebugLog {
    pub line: Vec<String>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Candidate {
    pub formatted_address: String,
    pub name: String,
    pub place_id: String,
    pub types: Vec<String>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct GoogleResponse {
    pub candidates: Vec<Candidate>,
    pub debug_log: DebugLog,
    pub status: String,
}

This all compiles and I can make the request, however the result that I am having in the String fields contain the original ". Is it supposed to be this way?

For instance, when printing one of the formatted addresses I get:

"result": "\"Street blabh blahab blahb\"",

When I really wanted just

"result": "Street blabh blahab blahb",

Am I doing something wrong or is this expected behavior?


Solution

  • I'll try to provide a simple example here.

    extern crate serde; // 1.0.80
    extern crate serde_json; // 1.0.33
    
    use serde_json::Value;
    
    const JSON: &str = r#"{
      "name": "John Doe",
      "age": 43
    }"#;
    
    fn main() {
        let v: Value = serde_json::from_str(JSON).unwrap();
        println!("{} is {} years old", v["name"], v["age"]);
    }
    

    (playground)

    will lead to

    "John Doe" is 43 years old

    The reason is, that v["name"] is not a String, but a Value instead (You can check that by adding the line let a: () = v["name"]; which will result in the error: expected (), found enum 'serde_json::Value').

    If you want a &str/String, you have to convert it first by using Value::as_str.

    If you change the println! line accordingly:

    println!("{} is {} years old", v["name"].as_str().unwrap(), v["age"]);
    

    it will print out:

    John Doe is 43 years old