1

I am trying to write a struct from a request payload to kafka, to do it I need to obtain the JSON string representing the struct. Currently, I am loading the object from the request using a struct that implements the Deserialize and Serialize traits from rocket::serde::json.

The code looks like this:

#[macro_use]
extern crate rocket;

use rocket::serde::{Serialize, Deserialize};
use rocket::serde::json::Json;

use rdkafka::config::ClientConfig;
use rdkafka::producer::{BaseRecord, FutureProducer};

#[derive(Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
struct Credential {
    metadata: String,
    data: String,
}

#[post("/", data="<c>")]
async fn insert_credentials(c: Json<Credential>) -> &'static str {

    // Do stuff with c

    let producer: &FutureProducer = &ClientConfig::new()
        .set("bootstrap.servers", "kafka:9200")
        .set("message.timeout.ms", "5000")
        .create()
        .expect("Producer creation error");

    let delivery_status = producer
        .send(
            FutureRecord::to("credentials_ingestion")
            .payload(Json(c).to_string())
            .key("MyKey")
        )
        .await;

    "Ok"
}

But I cannot get the .to_string() to work. I cannot find anything in the Rocket documentation on how to get the JSON string representation for the struct.

kmdreko
  • 42,554
  • 6
  • 57
  • 106
rafaelleru
  • 367
  • 1
  • 2
  • 19
  • You are confusing yourself wrt to `Json(c).to_string()`, you are probably looking for [`rocket::serde::json::to_string(&c)`](https://docs.rs/rocket/0.5.0-rc.2/rocket/serde/json/fn.to_string.html) – user2722968 Aug 02 '22 at 11:17
  • Yeah, that was the one I was looking for, I don't know why the compiler was raising an error when I was importing simultaneously Json and json. I updated that line to be `.payload(&json::to_string(&c).unwrap())` But now I am getting another error: ` the trait `Serialize` is not implemented for `Json`` @user2722968 – rafaelleru Aug 02 '22 at 11:42

1 Answers1

1

The Json type in Rocket is simply a wrapper around anything that is Serialize-able and is designed to encode or decode the value using the JSON format in other contexts: like through the FromData, FromUriParam, Responder, etc traits.

However, you cannot use Json to make a JSON string. For that, you'll want to make use of rocket::serde::json::to_string, which is just a re-export from the serde-json crate. What has tripped you up in the comment suggesting this is you need to take the contents out of the Json wrapper. You can use .into_inner() or use destructuring.

This is what you want:

use rocket::post;
use rocket::serde::json::{to_string, Json};
use rocket::serde::{Deserialize, Serialize};

use rdkafka::config::ClientConfig;
use rdkafka::producer::{FutureProducer, FutureRecord};
use rdkafka::util::Timeout;

#[derive(Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
struct Credential {
    metadata: String,
    data: String,
}

#[post("/", data = "<c>")]
async fn insert_credentials(c: Json<Credential>) -> &'static str {
    let credentials = c.into_inner();

    let producer: &FutureProducer = &ClientConfig::new()
        .set("bootstrap.servers", "kafka:9200")
        .set("message.timeout.ms", "5000")
        .create()
        .expect("Producer creation error");

    let delivery_status = producer
        .send(
            FutureRecord::to("credentials_ingestion")
                .payload(&to_string(&credentials).unwrap())
                .key("MyKey"),
            Timeout::Never,
        )
        .await;

    "Ok"
}
kmdreko
  • 42,554
  • 6
  • 57
  • 106