Reputation: 446
I am using reqwest
to perform a GET
request from https://httpbin.org.
Performing a request to a one-level json endpoint like https://httpbin.org/ip is easy
use std::collections::HashMap;
fn main() {
let body = reqwest::blocking::get("https://httpbin.org/ip")
.unwrap()
.json::<HashMap<String, String>>()
.unwrap();
dbg!(body);
}
However Im not sure how to go about other endpoints with a multi-level JSON response. How can I make a request to a multi-level JSON endpoint in reqwest
?
use std::collections::HashMap;
fn main() {
let body = reqwest::blocking::get("https://httpbin.org/get")
.unwrap()
.json::<HashMap<K, V>>()
.unwrap();
dbg!(body);
}
Upvotes: 4
Views: 1655
Reputation: 8484
Deserializing into serde_json::Value
, as @BallpointBen suggests certainly works. But in many cases, you'll then need to manually extract data from an arbitrary json value, which is tedious. There is a nicer way: deserialize into a rust struct:
struct Response { /* … */ }
let body = reqwest::blocking::get("https://httpbin.org/get?arg=blargh")
.unwrap()
.json::<Response>()
.unwrap();
To make that happen, you need to explain to serde how to work with your struct, e.g. like this:
use std::{collections::HashMap, net::IpAddr};
use serde::Deserialize;
#[derive(Deserialize)]
struct Response {
args: HashMap<String, String>,
// I'm making headers into another struct here to show some possibilities. You can of course make it a HashMap like args
headers: ResponseHeaders,
origin: IpAddr,
url: url::Url,
}
#[derive(Deserialize)]
#[serde(rename_all = "PascalCase")]
struct ResponseHeaders {
accept: String,
host: String,
#[serde(flatten)]
dynamic: HashMap<String, String>,
}
Deserializing into native rust structs is a bit of a rabbit hole, there's an small book on it.
Upvotes: 2