1

I want to write a util where I deserialize a given request body into the target type (T):

pub async fn read_json_body<'a, T>(req: &'a mut Request<Body>) -> T where T : Deserialize<'a> {
    let mut body = req.body_mut();
    let bytes = body::to_bytes(body).await.unwrap();
    let body_str = std::str::from_utf8(&*bytes).unwrap();
    serde_json::from_str::<T>(body_str).unwrap()
}

When I try to compile the code, I get the following error:

error[E0597]: `bytes` does not live long enough

21 |     pub async fn read_json_body<'a, T>(req: &'a mut Request<Body>) -> T where T : Deserialize<'a> {
   |                                 -- lifetime `'a` defined here
...
24 |         let body_str = std::str::from_utf8(&*bytes).unwrap();
   |                                              ^^^^^ borrowed value does not live long enough
25 |         serde_json::from_str::<T>(body_str).unwrap()
   |         ----------------------------------- argument requires that `bytes` is borrowed for `'a`
26 |     }
   |     - `bytes` dropped here while still borrowed

I understand that the Deserialize trait requires the lifetime 'a to outlive the deserialization, which is why assign the lifetime to the request reference. However I don't understand what my options are to fix this error in regard to the lifetime of the bytes object.

How do I fix this issue?

Requirements:

  • I don't want to move the request into the scope of the function
  • I don't want to extract the body from the request outside of the util, the request should be the parameter for the function, not the body
code-gorilla
  • 2,231
  • 1
  • 6
  • 21

1 Answers1

1

Use an owned version constraining to DeserializeOwned instead:

pub async fn read_json_body<T>(req: &mut Request<Body>) -> T where T : DeserializeOwned {
    let mut body = req.body_mut();
    let bytes = body::to_bytes(body).await.unwrap();
    let body_str = std::String::from_utf8(&*bytes).unwrap();
    serde_json::from_str::<T>(&body_str).unwrap()
}
Netwave
  • 40,134
  • 6
  • 50
  • 93
  • Thanks! Works for me. Just wondering: Is what I was trying to do impossible? I played around with different methods for reading the bytes, but nothing helped. – code-gorilla May 29 '22 at 12:25
  • 1
    @code-gorilla, using deserialize borrowing from the data usually is not a good idea. Most of the times you want to own the data. Altought it is useful sometimes. – Netwave May 29 '22 at 12:29