Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to derive serde::Deserialize for a struct with members with lifetimes [duplicate]

How can I derive Deserialize for a struct with objects with different or equal lifetimes inside?

playground

#[derive(Default, Debug, serde::Deserialize, serde::Serialize)]
struct B<'a> {
    b: &'a str,
}

#[derive(Default, Debug, serde::Deserialize, serde::Serialize)]
struct C<'a> {
    c: &'a str,
}

#[derive(Default, Debug, serde::Deserialize, serde::Serialize)]
struct A<'a> {
    b: B<'a>,
    c: C<'a>,
}

fn main() {
}

Rustc says this is impossible:

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'de` due to conflicting requirements
  --> src/main.rs:13:5
   |
13 |     b: B<'a>,
   |     ^
   |
note: first, the lifetime cannot outlive the lifetime 'de as defined on the impl at 11:26...
  --> src/main.rs:11:26
   |
11 | #[derive(Default, Debug, serde::Deserialize, serde::Serialize)]
   |                          ^^^^^^^^^^^^^^^^^^
   = note: ...so that the types are compatible:
           expected _IMPL_SERIALIZE_FOR_B::_serde::de::SeqAccess<'_>
              found _IMPL_SERIALIZE_FOR_B::_serde::de::SeqAccess<'de>
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 12:10...
  --> src/main.rs:12:10
   |
12 | struct A<'a> {
   |          ^^
   = note: ...so that the types are compatible:
           expected _IMPL_SERIALIZE_FOR_B::_serde::Deserialize<'_>
              found _IMPL_SERIALIZE_FOR_B::_serde::Deserialize<'_>

I don't understand what causes this problem and how I can fix it. There is a similar question but its answer does not cover this case.

like image 391
Victor Polevoy Avatar asked Aug 28 '19 12:08

Victor Polevoy


1 Answers

serde's lifetimes are complex enough to allow you to deserialize without copying data more than necessary. It's described in https://serde.rs/lifetimes.html

Apart for &str and &[u8], serde doesn't accept implicit borrowing.

For other struct parameters, if you want to borrow from the deserializer, you have to be explicit, which is done using a special #[serde(borrow)] attribute:

#[derive(Default, Debug, serde::Deserialize, serde::Serialize)]
struct A<'a> {

    #[serde(borrow)]
    b: B<'a>,

    #[serde(borrow)]
    c: C<'a>,
}
like image 176
Denys Séguret Avatar answered Oct 16 '22 06:10

Denys Séguret