How to fetch json with reqwest and handle with thiserror

💡 full source code is on github

foo.json

[ { "id": "foo", "type": "Cat", "weight": 123.45, "createdAt": "2022-09-01" }, { "id": "bar", "type": "Duck", "weight": 42.2424, "createdAt": "2022-08-01" } ]

Cargo.toml

[package] name = "fetch-json-reqwest-thiserror" version = "0.1.0" edition = "2021" [dependencies] # Use No-std support https://serde.rs/no-std.html serde = { version = "1.0", default-features = false, features = ["derive"] } serde_json = "1.0" # Use foe fetch, feature `json` for load json, `rustls-tls` for load via `TLS`. reqwest = { version = "0.11", default-features = false, features = ["json", "rustls-tls"] } # Use for handy return Result. anyhow = "1.0.65" # Use for async. tokio = { version ="1.22", features = ["full"] } thiserror = "1.0.50"

main.rs

use serde::{Deserialize, Serialize}; use thiserror::Error; #[derive(Serialize, Deserialize, Debug)] // This will auto convert form `camelCase` to `snake_case` #[serde(rename_all = "camelCase")] struct AnimalData { id: String, weight: f32, // This will auto convert form "createdAt" to `created_at` created_at: String, } // 👇 Derive from thiserror::Error #[derive(Error, Debug)] enum CustomError { #[error("Request failed: {0}")] RequestError(reqwest::Error), #[error("JSON parsing error: {0}")] JsonParseError(reqwest::Error), } async fn fetch(url: &str) -> Result<Vec<AnimalData>, CustomError> { let response = reqwest::get(url).await.map_err(CustomError::RequestError)?; let animals = response .json::<Vec<AnimalData>>() .await .map_err(CustomError::JsonParseError)?; Ok(animals) } #[tokio::main] async fn main() { let animals = match fetch("https://raw.githubusercontent.com/gist-rs/book/main/examples/r4/20-fetch-json-reqwest/src/foo.json").await { Ok(animals) => { println!("{animals:#?}"); // Will return parsed JSON as Vec<AnimalData> type. animals } Err(err) => { // Will yelling. println!("No animals!: {:?}", err); // Will return empty vector animals. Vec::from([]) } }; println!("{animals:#?}"); }

🤷 reqwest+TLS is not runnable via Rust Playground so output is shown below.

Run
Ok( [ AnimalData { id: "foo", weight: 123.45, created_at: "2022-09-01", }, AnimalData { id: "bar", weight: 42.2424, created_at: "2022-08-01", }, ], )