我在为 struct 创建通用向量时遇到了一个问题.

#[derive(Serialize)]
struct Card {
    sections: Vec<Section<WidgetTrait>>
}

#[derive(Serialize)]
struct Section<T: WidgetTrait> {
    header: String,
    widgets: Vec<T>
}

这给我带来了一个错误,Sized没有实现,WidgetTrait的大小在编译时是未知的.

我的下一次try 是使用Box<WidgetTrait>,就像这样:

#[derive(Serialize)]
struct Section {
    header: String,
    widgets: Vec<Box<WidgetTrait>>
}

Playground

这让我犯了一个错误:

error[E0277]: the trait bound `WidgetTrait: serde::Serialize` is not satisfied
  --> src/main.rs:11:10
   |
11 | #[derive(Serialize)]
   |          ^^^^^^^^^ the trait `serde::Serialize` is not implemented for `WidgetTrait`
   |
   = note: required because of the requirements on the impl of `serde::Serialize` for `std::boxed::Box<WidgetTrait>`
   = note: required because of the requirements on the impl of `serde::Serialize` for `std::vec::Vec<std::boxed::Box<WidgetTrait>>`
   = note: required by `serde::ser::SerializeStruct::serialize_field`

我的目标是让Section struct中的widgets vector能够接受实现WidgetTrait trait的不同类型的widget,就像使用接口一样.

推荐答案

要序列化Serde-trait对象,应该使用erased-serde.

#[macro_use]
extern crate serde_derive;

#[macro_use]
extern crate erased_serde;

extern crate serde;
extern crate serde_json;

#[derive(Serialize)]
struct Card {
    sections: Vec<Section>,
}

#[derive(Serialize)]
struct Section {
    header: String,
    widgets: Vec<Box<WidgetTrait>>,
}

#[derive(Serialize)]
struct Image {
    image_url: String,
}

#[derive(Serialize)]
struct KeyValue {
    top_label: String,
    content: String,
}

trait WidgetTrait: erased_serde::Serialize {}
impl WidgetTrait for Image {}
impl WidgetTrait for KeyValue {}

serialize_trait_object!(WidgetTrait);

fn main() {
    let card = Card {
        sections: vec![
            Section {
                header: "text".to_owned(),
                widgets: vec![
                    Box::new(Image {
                        image_url: "img".to_owned(),
                    }),
                    Box::new(KeyValue {
                        top_label: "text".to_owned(),
                        content: "text".to_owned(),
                    }),
                ],
            },
        ],
    };

    println!("{}", serde_json::to_string_pretty(&card).unwrap());
}

Rust相关问答推荐

捕获Rust因C++异常而产生panic

将此字符串转换为由空格字符分隔的空格

在actix—web中使用Redirect或NamedFile响应

PyReadonlyArray2到Vec T<>

使用pyo3::Types::PyIterator的无限内存使用量

通过不同的字段进行散列和排序的 struct (需要不同的EQ实现)

Rust 的多态现象.AsRef与Derf

如何在函数中返回自定义字符串引用?

变量需要parse()中的显式类型

将一个泛型类型转换为另一个泛型类型

如何获取光标下的像素 colored颜色 ?

为什么 js_sys Promise::new 需要 FnMut?

如何以与平台无关的方式将OsString转换为utf-8编码的字符串?

`use` 和 `crate` 关键字在 Rust 项目中效果不佳

为什么这个闭包没有实现Fn?

如何为整数切片定义一个带有额外函数的特性别名?

如何从 rust 中的同一父目录导入文件

rust tokio::spawn 在 mutexguard 之后等待

将原始可变指针传递给 C FFI 后出现意外值

用逗号分隔字符串,但在标记中使用逗号