I'm decoding a reqwest::Response
to JSON. Usually that works fine, but in some rare cases the remote server returns a response that doesn't fit my struct
that I'm using for deserialization. In those cases I'd like to print out the original response text for further debugging.
However, I'm having trouble to both do the JSON deserialization and printing out the response body. What I'd like to do is
#[derive(serde::Deserialize)]
struct MyData {
// ...
}
async fn get_json(url: &str) -> Result<MyData, reqwest::Error> {
let response = reqwest::get(url).await?;
let text = response.text().await?;
response
.json::<MyData>().await
.map_err(|err| {
println!(
"Could not decode response from {}: {}", url, text
);
err
})
}
But that doesn't work because response.text
takes self
, so I cannot re-use response
for response.json
.
Based on code from another answer (also recommended in this answer) I've found this approach:
let response = reqwest::get(url).await?;
let text = response.text().await?;
serde_json::from_str(&text).map_err(...)
However, serde_json::from_str
returns a Result<_, serde_json::Error>
, so this approach would complicate my error handling because the calls before all return Result<_, reqwest::Error>
. I'd prefer my function to also return the latter, not some custom error wrapper.
What is an idiomatic way of achieving my goal?
reqwest
doesn't have a way to customize how json parsing is handled and it doesn't allow creatingError
s outside the crate. So you have to use a different error type. Perhaps one of the many error-handling crates (anyhow
,thiserror
,snafu
) can help ease that burden though. – Meant