2

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);
}
Pro Poop
  • 357
  • 5
  • 14
  • 2
    The easiest way is probably by deserializing into `serde_json::Value`, which is an enum with a 1-1 mapping to JSON – BallpointBen Feb 04 '22 at 03:28

1 Answers1

1

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.

Caesar
  • 6,733
  • 4
  • 38
  • 44