Search code examples
jsonrustserderust-rocket

Rocket - handle untyped json body with Rocket and okapi


I'm trying to create some simple REST API which will receive some untyped json data for further processing, but I really don't know the structure yet. What I have so far is this:

#[openapi]
#[post("/api/json-data", format = "json", data = "<data>")]
fn send_data(data: Json<String>) -> Json<ApiResponse> {

  Json(DataProcessor::process(data.into_inner()))
}

later on I will use serde to get the untyped JSON value

pub fn process(data: String) {
  let json: Value = serde_json::from_str(data.as_str()).unwrap();
}

The problem is, when I call this endpoint with some JSON data I get the following error:

Couldn't parse JSON body: Error("invalid type: map, expected a string"

Just doing fn send_data(data: String) won't work either, as then #[openapi] complaints about

the trait `OpenApiFromData<'_>` is not implemented for `std::string::String`

What is the correct way to handle untyped JSON data with Rocket and okapi?

I really appreciate any help.


Solution

  • I think I can answer my own question, just in case someone else is having trouble with this.

    The request body's data type needs to be HashMap<&str, serde_json::Value>

    So the API definition should look like this:

    #[openapi]
    #[post("/api/json-data", format = "json", data = "<data>")]
    fn send_data(data: Json<HashMap<&str, Value>>) -> Json<ApiResponse> {
    
      Json(DataProcessor::process(data.into_inner()))
    }
    

    which actually makes total sense regarding the error

    Couldn't parse JSON body: Error("invalid type: map, expected a string")