Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert serde_json::error::Error to reqwest::error::Error?

Tags:

rust

reqwest v0.9 has serde v1.0 as a dependency and as a result implements converting serde_json errors into reqwest error.

In my code, I am doing some deserialization using serde_json instead of using .json() method that comes with reqwest.

// reqwest = "0.9"
// serde = { version = "1.0", features = ["derive"] }
// serde_json = "1.0"

pub fn get_meta(client: &reqwest::Client) -> Result<Meta, reqwest::Error> {
    let mut resp = client
        .get("http://localhost:8080/requests/playlist.json")
        .send()?;

    let data: Value = serde_json::from_str(&resp.text()?).unwrap();
    let data = data["children"][0]["children"].clone();
    let metas: Vec<Meta> = serde_json::from_value(data).unwrap();
    let meta: Meta = metas.last().expect("nothing is playing").clone();
    Ok(meta)
}

Currently, I am trying to return serde_json errors as reqwest errors. Changing let metas: Vec<Meta> = serde_json::from_value(data).unwrap(); to let metas: Vec<Meta> = serde_json::from_value(data)?; fails with the following error:

 the trait `std::convert::From<serde_json::error::Error>` is not implemented for `reqwest::error::Error`

Is it possible to convert serde_json::error::Error to reqwest::error::Error by wrapping it inside Kind::Json error enum of reqwest, or do I have to make a custom error enum that encompasses both as mentioned in this article?

like image 388
ducaale Avatar asked Jan 05 '20 22:01

ducaale


1 Answers

No, you can't construct reqwest::Error value yourself because it:

  • has non-public fields
  • does not expose public constructors
  • does not have From implementations for public types

Fortunately both reqwest::Error and serde_json::error::Error implement std::error::Error trait. Following the recommendation from the blog post you linked, the anyhow crate is very helpful here:

// reqwest = "0.9"
// serde = { version = "1.0", features = ["derive"] }
// serde_json = "1.0"
// anyhow = "1.0"

pub fn get_meta(client: &reqwest::Client) -> Result<Meta, anyhow::Error> {
    let mut resp = client
        .get("http://localhost:8080/requests/playlist.json")
        .send()?;

    let data: Value = serde_json::from_str(&resp.text()?).unwrap();
    let data = data["children"][0]["children"].clone();
    let metas: Vec<Meta> = serde_json::from_value(data).unwrap();
    let meta: Meta = metas.last().expect("nothing is playing").clone();
    Ok(meta)
}
like image 93
edwardw Avatar answered Oct 02 '22 00:10

edwardw