Serde сериализуется с типом прокси для удаленного объекта - PullRequest
2 голосов
/ 28 апреля 2020

Как создать прокси-объект сериализатора для удаленного типа с помощью Serde? Вот минимальный пример ( детская площадка ):

use serde; // 1.0.104
use serde_json; // 1.0.48

struct Foo {
    bar: u8,
}

impl Foo {
    pub fn new() -> Self {
        Foo { bar: 10 }
    }

    pub fn val(&self) -> u8 {
        self.bar
    }
}

#[derive(serde::Serialize)]
#[serde(remote = "Foo")]
struct Bar {
    #[serde(getter = "Foo::val")]
    val: u8,
}

fn main() {
    let foo = Foo::new();
    let res = serde_json::to_string(&foo).unwrap();
    println!("{}", res);
}

Не удается найти реализацию:

error[E0277]: the trait bound `Foo: _IMPL_SERIALIZE_FOR_Bar::_serde::Serialize` is not satisfied
    --> src/main.rs:27:37
     |
27   |     let res = serde_json::to_string(&foo).unwrap();
     |                                     ^^^^ the trait `_IMPL_SERIALIZE_FOR_Bar::_serde::Serialize` is not implemented for `Foo`
     | 
    ::: /playground/.cargo/registry/src/github.com-1ecc6299db9ec823/serde_json-1.0.48/src/ser.rs:2233:8
     |
2233 |     T: Serialize,
     |        --------- required by this bound in `serde_json::ser::to_string`

1 Ответ

3 голосов
/ 28 апреля 2020

#[serde(remote = "Foo")] не может нарушить правило сироты, поэтому на самом деле не реализует черту для типа Foo.

. Вы должны использовать ее с #[serde(with = "...")].

. Простой способ сделать это, чтобы создать небольшую оболочку для сериализации:

#[derive(serde::Serialize)]
struct FooWrapper<'a>(#[serde(with = "Bar")] &'a Foo);

и использовать ее как serde_json::to_string(&FooWrapper(&foo)) ( постоянная ссылка на игровую площадку ).

Это будет сериализовать Foo как вы ожидаете, используя удаленное определение Bar.

Для десериализации вы можете использовать Bar::deserialize, и вы получите Foo напрямую.

См. Также:

...