Rust Reqwest Crate - GET JSON Object

When programming in Rust, the reqwest HTTP client library can be utilized to make HTTP requests and receive responses from a server. Once a response is received, it can be converted into a JSON object for further processing. 

It's worth noting that if the structure of the response is already known, you can use a HashMap object to store the response. This method is ideal when the response is known. On the other hand, if you’re unaware of the structure of the response, such as with dynamic responses, the serde_json::Value object can be used to deserialize the response. This allows you to access the data within the response object, regardless of its structure.

In this post, I will show you how to get JSON objects using the reqwest HTTP client library on known and unknown JSON structures and deserialize the results. You can also find the code presented in these examples on GitHub.

Rust cargo add -  tokio, serde_json, reqwest crates

We can use the Rust langs cargo add command to add the following crates to our Cargo.toml file.

First, we'll be using asynchronous requests. We'll first add the tokio asynchronous runtime for Rust with full features. From the command-line, we can run the following cargo commands, which will add the required dependencies to our Rust project for us.

cargo add tokio -F full 

Next, we'll also add the reqwests crate with cargo to have access to the reqwests HTTP client library. Since we will be deserializing the response body as JSON, we need to import the JSON feature.

cargo add reqwest -F json

Finally, we add the serde_json crate in order to access its serde_json::value::Value enum object.

cargo add serde_json

With these crates added, we can move onto our main function and write our main Rust logic to perform HTTP GET requests with the reqwest crate and get JSON objects.

Rust Using tokio, serde_json, reqwest crates

Once we have access to the tokio, serde_json, and reqwest crates we'll import them into our main.rs file.

use reqwest;
use serde_json;

We'll also import the HashMap object, part of the Rust standard library.

use std::collections::HashMap;

Above our main function, we'll add the #[tokio::main] macro, which will transform our main function into an asynchronous function.

Rust Get JSON Response - Using HashMap

Inside our main function, we can write the following logic in order to make the HTTP request to get the JSON object using reqwest. Knowing the return structure, we can use a HashMap object to populate our response.

// KNOWN RETURN - HashMap
const URL2: &str = "https://httpbin.org/ip";
match reqwest::get(URL2).await {
    Ok(resp) => {
        let json = resp.json::<HashMap<String, String>>().await?;
        println!("{:?}", json)
    }
    Err(err) => {
        println!("Reqwest Error: {}", err)
    }
}

In the above code sample:

  1. we've defined a const URL1. This variable will reference a string, the URL to https://httpbin.org/ip, which will fetch our internet routable IP.

  2. To send an HTTP request to this URL, we use the reqwest::get method, and since we are using an asynchronous request, we will await the return.

  3. If the response is successful without error, we'll deserialize the json response with the json() function and then store the <HashMap<String, String>>() into a json variable

  4. Finally, we will print the value of our json object.

Notice we define our HashMap as follows, <HashMap<String, String>> the returned object is a simple JSON data struct with a String of "origin" as a key, and a String value of our internet routable IP address. The struct is as follows: {"origin": "IP ADDRESS"}. 

This is a simple JSON object, but what happens if we do not know the structure of the returned JSON object? For that, we can deserialize the HTTP response into a serde_json::Value.

Rust Get JSON Response - serde_json::Value

If we are unsure of the JSON structure returned from an HTTP request, such as with dynamic JSON data, we can deserialize the JSON response into a serde_json::Value. 

// UNKNOWN RETURN - serde_json::Value
const URL1: &str = "https://dummyjson.com/products/1";
match reqwest::get(URL1).await {
    Ok(resp) => {
        let json: serde_json::Value = resp.json().await?;
        println!("{:?}", json)
    }
    Err(err) => {
        println!("Reqwest Error: {}", err)
    }
}

The basic HTTP request structure in the above example is the same as with the HashMap example; however, in this example, we pass the deserialized JSON object to the JSON variable, which is a serde_json::Value enum type. In the Rust programming language, the serde_json::value is a Value enum, a loosely typed way of representing any valid JSON value.

The serde_json::value::Value enum represents a JSON value, which is defined by the following structure and can have the following value types:

pub enum Value {
    Null,
    Bool(bool),
    Number(Number),
    String(String),
    Array(Vec<Value>),
    Object(Map<String, Value>),
}

This enum object allows programmers to work flexibly and conveniently with JSON data in various Rust programs.

Reqwest Get JSON: Full Example

Below is a full example of making an HTTP GET request with reqwest and deserializing using the json() method and storing the response using HashMap and serde_json::Value.

If you’d like a complete example of the code presented, you can also find these code examples on GitHub.

Conclusion: Using Reqwest Deserialize JSON Data

Mastering HTTP requests and JSON deserialization in Rust opens up possibilities. The reqwest HTTP client library helps you handle response structures effectively. HashMap objects work best for familiar response structures, while serde_json::Value is invaluable for unknown or dynamic structures. 

You can confidently tackle web-based tasks by mastering these techniques, from API integrations to data processing. Rust, coupled with reqwest and serde_json, equips you with the tools to conquer web development challenges with finesse and efficiency.

I hope you found this post on reqwest and JSON deserializtion informative. If you have any questions, feel free to ask on social media or shoot me an email!

Previous
Previous

Install Rust on Windows: From the Terminal

Next
Next

Cybersecurity - Secure by Default vs. Secure by Design