如何创建可以使用Serde序列化并保留类型信息的通用结构?

问题描述 投票:2回答:1

我想使用Serde序列化通用的数据结构。

我的库的用户应该能够提供自己的结构来实现SerializeDeserialize。我应该能够获取他们序列化数据的值的原始类型信息。

我该怎么做呢?

我试过这样的事情:

#[derive(Serialize, Deserialize)]
struct Message<V> {
    key: Key,
    value: V,
}

我希望在反序列化数据后取回V的类型。

这是做到这一点的方式还是偏离轨道?

我希望用户能够扩展可能的值/类型。我想要枚举的行为,但是用户可以灵活地添加自己的结构作为可能的候选者。与this code类似,但它们都需要独特的ID。

generics serialization rust traits serde
1个回答
2
投票

我很确定这在一般意义上是完全不可能的。

每种类型都能够控制自己的序列化。这意味着多种类型最终可能会序列化为相同的值:

#[derive(Debug, Deserialize, Serialize)]
struct Age(i32);

#[derive(Debug, Deserialize, Serialize)]
struct Weight(i32);

fn main() {
    let a = Age(42);
    let a_str = serde_json::to_string(&a).unwrap();
    println!("{}", a_str); // 42
    let b: Weight = serde_json::from_str(&a_str).unwrap();
    println!("{:?}", b);
}

您可以尝试在标识类型的序列化数据中构建标记,但最终会出现同样的问题:总是存在冲突的可能性。

更基本的是,这样的概念在Rust中无效,其中每种类型在编译时必须具有已知的大小。无法将反序列化为未知大小的变量。

同样从根本上说,你会为通用V提供什么类型?编译代码时,不能“忘记”指定所有泛型类型。

因此,通常这样的事情甚至都没有出现。如果用户使用具体类型调用序列化代码,则可以使用相同的具体类型调用反序列化代码。

我想要枚举的行为,但是用户可以灵活地添加自己的结构。

这听起来像一个特质对象。

也可以看看:

© www.soinside.com 2019 - 2024. All rights reserved.