我正在尝试解决序列化和反序列化的问题Box<SomeTrait>.我知道在封闭类型层次结构的情况下,推荐的方法是使用枚举,并且序列化没有问题,但在我的情况下使用枚举是不合适的解决方案.
起初我尝试使用Serde,因为它是事实上的Rust序列化机制.Serde能够序列化Box<X>但不能在何时X成为特征.该Serialize特性不能为特征的对象实现的,因为它具有通用的方法.这个特殊问题可以通过使用擦除serde来解决,因此序列化Box<SomeTrait>可以工作.
主要问题是反序列化.要反序列化多态类型,您需要在序列化数据中使用某种类型标记.该标记应首先反序列化,然后用于动态获取将返回的函数Box<SomeTrait>.
std::any::TypeId可以用作标记类型,但主要问题是如何动态获取反序列化函数.我不考虑为应用程序初始化期间应手动调用的每种多态类型注册函数的选项.
我知道有两种可能的方法:
但Rust中没有这些选项.如果有的话,如何在Rust中添加多态对象的反序列化?
我有一个包含自己类型的子的结构.这些孩子被包裹在Arcs中,我在调用serde_json::to_string它时遇到问题.我的结构是:
#[derive(Serialize, Deserialize)]
pub struct Category {
pub id: i32,
pub name: String,
pub parent_id: i32,
pub children: Vec<Arc<Category>>,
}
Run Code Online (Sandbox Code Playgroud)
这会产生错误the trait 'serde::Serialize' is not implemented for 'std::sync::Arc<db::queries::categories::Category>'我尝试了一些不同的方法来使序列化工作,例如:
#[serde(serialize_with = "arc_category_vec")]
pub children: Vec<Arc<Category>>
Run Code Online (Sandbox Code Playgroud)
fn arc_category_vec<S>(value: &Vec<Arc<Category>>, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut seq = serializer.serialize_seq(Some(value.len()))?;
for e in value {
seq.serialize_element(e.as_ref())?;
}
seq.end()
}
Run Code Online (Sandbox Code Playgroud)
这没有帮助,因为我得到相同的错误.我也尝试过:
impl Serialize for Arc<Category> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where …Run Code Online (Sandbox Code Playgroud) 我试图为结构创建一个通用向量时遇到了问题.这是我的第一次尝试:
#[derive(Serialize)]
struct Card {
sections: Vec<Section<WidgetTrait>>
}
#[derive(Serialize)]
struct Section<T: WidgetTrait> {
header: String,
widgets: Vec<T>
}
Run Code Online (Sandbox Code Playgroud)
这使我遇到了一个Sized未实现的错误,并且WidgetTrait在编译时未知大小.
我的下一次尝试是这样使用Box<WidgetTrait>:
#[derive(Serialize)]
struct Section {
header: String,
widgets: Vec<Box<WidgetTrait>>
}
Run Code Online (Sandbox Code Playgroud)
这导致了一个错误:
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 …Run Code Online (Sandbox Code Playgroud)