How can I (de)serialize object that has trait field to .ron format with an erased-serde crate?

huangapple go评论70阅读模式
英文:

How can I (de)serialize object that has trait field to .ron format with an erased-serde crate?

问题

以下是您要翻译的内容:

[dependencies]
ron = "0.8"
serde = "1.0"
erased-serde = "0.3"
use serde::Serialize;

trait Temp {
    fn temp(&self);
}

struct TempNum {
    num: i32,
}

impl Temp for TempNum {
    fn temp(&self) {}
}

#[derive(Serialize)]
struct IncludeTrait {
    temps: Vec<Box<dyn Temp>>, // 这是问题
}

fn main() {
    let object = IncludeTrait { temps: vec![Box::new(TempNum { num: 123 })] };
    let str = ron::to_string(&object).unwrap();
    let object: IncludeTrait = ron::from_str(&str).unwrap();
}

请注意,我已经将HTML实体编码(如&amp;&lt;)转换为正常的Rust代码。

英文:

the erased-serde example for json and cbor.

https://github.com/dtolnay/erased-serde

how can i change object with trait fields to ron format str?

[dependencies]
ron = &quot;0.8&quot;
serde = &quot;1.0&quot;
erased-serde = &quot;0.3&quot;
use serde::Serialize;

trait Temp {
    fn temp(&amp;self);
}

struct TempNum {
    num: i32,
}

impl Temp for TempNum {
    fn temp(&amp;self) {}
}

#[derive(Serialize)]
struct IncludeTrait {
    temps: Vec&lt;Box&lt;dyn Temp&gt;&gt;, // this is problem
}

fn main() {
    let object = IncludeTrait { temps: vec![Box::new(TempNum { num: 123 })], };
    let str = ron::to_string(&amp;object).unwrap();
    let object: IncludeTrait = ron::from_str(&amp;str).unwrap();
}

答案1

得分: 2

为使用 erased-serde,您需要将 erased_serde::Serialize 声明为您的特质的超特质,并通过它为 dyn Temp 实现 Serialize(您可以使用 erased_serde::serialize_trait_object!() 来实现这一点):

use serde::Serialize;

trait Temp: erased_serde::Serialize {
    fn temp(&amp;self);
}

erased_serde::serialize_trait_object!(Temp);

#[derive(Serialize)]
struct TempNum {
    num: i32,
}

impl Temp for TempNum {
    fn temp(&amp;self) {}
}

#[derive(Serialize)]
struct IncludeTrait {
    temps: Vec&lt;Box&lt;dyn Temp&gt;&gt;
}

然而,即使这样只有支持序列化,从您的代码来看,您似乎还希望支持反序列化。特质对象的反序列化是复杂的 - 我们无法知道要构建什么对象。但是我们有 typetag crate 来处理这个问题。只需在特质和实现上方添加 #[typetag::serde]

use serde::{Deserialize, Serialize};

#[typetag::serde]
trait Temp {
    fn temp(&amp;self);
}

#[derive(Serialize, Deserialize)]
struct TempNum {
    num: i32,
}

#[typetag::serde]
impl Temp for TempNum {
    fn temp(&amp;self) {}
}

#[derive(Serialize, Deserialize)]
struct IncludeTrait {
    temps: Vec&lt;Box&lt;dyn Temp&gt;&gt;
}

注意:我将HTML实体(如 &amp;&lt;)保留为原样,您在代码中可能需要将它们替换为正常的符号。

英文:

To use erased-serde, you need to declare erased_serde::Serialize as a supertrait of your trait and implement Serialize for dyn Temp via that (you can do that with erased_serde::serialize_trait_object!()):

use serde::Serialize;

trait Temp: erased_serde::Serialize {
    fn temp(&amp;self);
}

erased_serde::serialize_trait_object!(Temp);

#[derive(Serialize)]
struct TempNum {
    num: i32,
}

impl Temp for TempNum {
    fn temp(&amp;self) {}
}

#[derive(Serialize)]
struct IncludeTrait {
    temps: Vec&lt;Box&lt;dyn Temp&gt;&gt;,
}

However, even that helps only with serialization, and from your code it looks like you also want to support deserialization. Deserialization of trait object is complicated - we can't know what object to construct. But we have the typetag crate for that. Just add #[typetag::serde] on top of the trait and the impls:

use serde::{Deserialize, Serialize};

#[typetag::serde]
trait Temp {
    fn temp(&amp;self);
}

#[derive(Serialize, Deserialize)]
struct TempNum {
    num: i32,
}

#[typetag::serde]
impl Temp for TempNum {
    fn temp(&amp;self) {}
}

#[derive(Serialize, Deserialize)]
struct IncludeTrait {
    temps: Vec&lt;Box&lt;dyn Temp&gt;&gt;,
}

huangapple
  • 本文由 发表于 2023年2月14日 01:46:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/75439488.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定