How to create a HashMap that receives different types?

I am creating a project in which I need to send JSON to an application using the REQWEST library, and some values ​​cannot be STRINGS. However, I cannot create a dynamic HashMap, my alternative was to create an Enum, but I am not able to work with it when sending the data in the request, can you help me?

This is how I'm sending

let mut json_data = HashMap::new();
json_data.insert("jql","project=ABC");
json_data.insert("startAt",0);
json_data.insert("maxResults",1);

    let client = reqwest::Client::new();

    let resp = client
        .post("https://site.com/rest/api/2/search")
         .json(&json_data)
        .send()
        .await
        .unwrap();

Using enum have the problem regarding the type that is sent as "json" by reqwest

enum JsonValue {
    String(String),
    Integer(i32),
}

    let mut json_data = HashMap::new();
    
    // Insira os valores no HashMap
    json_data.insert("jql".to_string(), JsonValue::String("project=ABC".to_string()));
    json_data.insert("startAt".to_string(), JsonValue::Integer(0));
    json_data.insert("maxResults".to_string(), JsonValue::Integer(1));

you need to implement (or derive) serde::Serialize for your enum type so it can be convert to json as the http request payload data.

one possible alternative is to use the serde_json crate directly. you can the serde_json::Value type, it implements From trait for relevant built-in types already, it can be used like this:

use serde_json::{json, Value};
// create an empty `Object` variant of `Value`
let mut object = json!({});
// get a mut reference to the inner hash map for convenience 
let map = object.as_object_mut().unwrap();
// insert string value
map.insert("jql".into(), "project=ABC".into());
// insert integer value
map.insert("startAt".into(), 0.into());
// the `Value` type implements `Serialize` out of the box
client.post(url)
    .json(&object)
    .send()
    .await
    .unwrap();
3 Likes

Here's what that would look like with a proper serde type:

#[derive(serde::Serialize)]
#[serde(rename_all = "camelCase")]
struct Data<'a> {
    jql: &'a str,
    start_at: i32,
    max_results: i32,
}
let data = Data {
    jql: "project=ABC",
    start_at: 0,
    max_results: 1,
};

let client = reqwest::Client::new();

let resp = client
    .post("https://site.com/rest/api/2/search")
    .json(&data)
    .send()
    .await
    .unwrap();
4 Likes

You can also use this

let json_data = json!({
    "jql": "project=ABC",
    "startAt": 0,
    "maxResults": 1
 });
let client = reqwest::Client::new();
let resp = client
    .post("https://site.com/rest/api/2/search")
    .json(&json_data)
    .send()
    .await
    .unwrap();
1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.