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

标签 generics serialization rust traits serde

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

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

我该怎么做?

我试过这样的:

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

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

这是这样做的方式还是我偏离了轨道?

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

最佳答案

我敢肯定,这在一般意义上是完全不可能的。

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

#[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 中是无效的,因为 Rust 中每种类型都必须在编译时具有已知大小。无法反序列化为未知大小的变量。

同样重要的是,您将为通用 V 提供什么类型?编译代码时不能“忘记”指定所有泛型类型。

正因为如此,通常这样的事情根本不会出现。如果用户使用具体类型调用您的序列化代码,他们可以使用相同的具体类型调用您的反序列化代码。

I want the behavior of enums, but flexibility for the user to add their own structs.

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

另见:

关于generics - 如何创建一个可以用 Serde 序列化并保留类型信息的通用结构?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49552876/

相关文章:

c# - DataContract XML 序列化和 XML 属性

rust - 当 Iterator::map 返回 Result::Err 时,如何停止迭代并返回错误?

java - 为什么我不能扩展接口(interface) "generic method"并将其类型缩小到继承的接口(interface) "class generic"?

android - Kotlin函数返回数据类错误,类型不匹配,必填: <Data Class>#1

c# - 将 EF 模型序列化为 Json 时的循环引用

c# - 将字节数组直接反序列化为 JSON.Net 中的对象

rust - 预期的向量但找到了结构集合::vec::Vec

testing - 如何获取所有 cargo 测试的列表?

java - 如何使用两个对象中最特殊的类型作为返回类型?

Java - 使用 WatchEvent 抑制未经检查的转换警告是否安全?