How to fix reqwest json decode errors?

Viewed 1764

When I run the following code:

use exitfailure::ExitFailure;
use reqwest::Url;
use serde_derive::{Deserialize, Serialize};
use std::env;

#[derive(Serialize, Deserialize, Debug)]
struct CompanyInfo {
    country: String,
    currency: String,
    exchange: String,
    ipo: String,
    marketCapitalization: u128,
    name: String,
    phone: String,
    shareOutstanding: f64,
    ticker: String,
    weburl: String,
    logo: String,
    finnhubIndustry: String,
}

impl CompanyInfo {
    async fn get(symbol: &String, api_key: &String) -> Result<Self, ExitFailure> {
        let url = format!(
            "https://finnhub.io/api/v1/stock/profile2?symbol={}&token={}",
            symbol, api_key
        );

        let url = Url::parse(&*url)?;
        let res = reqwest::get(url).await?.json::<CompanyInfo>().await?;

        Ok(res)
    }
}

#[tokio::main]
async fn main() -> Result<(), ExitFailure> {
    let api_key = "MY API KEY".to_string();
    let args: Vec<String> = env::args().collect();
    let mut symbol: String = "AAPL".to_string();

    if args.len() < 2 {
        println!("Since you didn't specify a company symbol, it has defaulted to AAPL.");
    } else {
        symbol = args[1].clone();
    }

    let res = CompanyInfo::get(&symbol, &api_key).await;
    println!("{:?}", res);

    Ok(())
}

I get an error: Err(error decoding response body: expected ',' or '}' at line 1 column 235). For another API, this code with a similar structure worked. How do you solve this issue with reqwest?

1 Answers

Typically, the error decoding response body means that you tried to deserialize an HTTP response that is in a given format, but the response body wasn't valid for that format. In your case, you are trying to deserialize JSON, so the error means that the thing you are trying to deserialize probably isn't valid JSON, or perhaps it is valid JSON but your expected JSON structure doesn't match the structure returned from the server. The server might have goofed in creating it's JSON, or perhaps it is returning a response body that isn't actually JSON for a specific reason (for example, some APIs will not return JSON if they are returning a 500 response).

In order to debug and fix this, you need to know exactly what the response body looks like that you are attempting to parse. One way to do this is to split the parsing of the code into two parts: one that gets the text, and another that tries to parse. For example, for debugging purposes you can print out the response that you have received by doing something like the following:

// Split up the JSON decoding into two steps.
// 1.) Get the text of the body.
let response_body = reqwest::get(url).await?.text().await?;
println!("Response Body: {}", response_body);

// 2.) Parse the results as JSON.
let res: CompanyInfo = serde_json::from_str(&response_body)?;

This code should will probably fail just as before, but now you'll have the response body that failed printed out. At that point, you'll have to analyze the response body, at which point it will hopefully become obvious why it doesn't work.

Related