英文:
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实体编码(如&
和<
)转换为正常的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 = "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>>, // this is problem
}
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();
}
答案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(&self);
}
erased_serde::serialize_trait_object!(Temp);
#[derive(Serialize)]
struct TempNum {
num: i32,
}
impl Temp for TempNum {
fn temp(&self) {}
}
#[derive(Serialize)]
struct IncludeTrait {
temps: Vec<Box<dyn Temp>>
}
然而,即使这样只有支持序列化,从您的代码来看,您似乎还希望支持反序列化。特质对象的反序列化是复杂的 - 我们无法知道要构建什么对象。但是我们有 typetag
crate 来处理这个问题。只需在特质和实现上方添加 #[typetag::serde]
:
use serde::{Deserialize, Serialize};
#[typetag::serde]
trait Temp {
fn temp(&self);
}
#[derive(Serialize, Deserialize)]
struct TempNum {
num: i32,
}
#[typetag::serde]
impl Temp for TempNum {
fn temp(&self) {}
}
#[derive(Serialize, Deserialize)]
struct IncludeTrait {
temps: Vec<Box<dyn Temp>>
}
注意:我将HTML实体(如 &
和 <
)保留为原样,您在代码中可能需要将它们替换为正常的符号。
英文:
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(&self);
}
erased_serde::serialize_trait_object!(Temp);
#[derive(Serialize)]
struct TempNum {
num: i32,
}
impl Temp for TempNum {
fn temp(&self) {}
}
#[derive(Serialize)]
struct IncludeTrait {
temps: Vec<Box<dyn Temp>>,
}
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(&self);
}
#[derive(Serialize, Deserialize)]
struct TempNum {
num: i32,
}
#[typetag::serde]
impl Temp for TempNum {
fn temp(&self) {}
}
#[derive(Serialize, Deserialize)]
struct IncludeTrait {
temps: Vec<Box<dyn Temp>>,
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论