我想使用Serde序列化通用的数据结构。
我的库的用户应该能够提供自己的实现Serialize
和Deserialize
的结构。我应该能够获取他们序列化数据的值的原始类型信息。
我将如何做到这一点?
我尝试过这样的事情:
#[derive(Serialize, Deserialize)]
struct Message<V> {
key: Key,
value: V,
}
我希望在反序列化数据后取回V
的类型。
这是做到这一点的方式还是偏离轨道?
我希望用户能够扩展可能的值/类型。我想要枚举的行为,但是用户可以灵活地添加自己的结构作为可能的候选者。与this code类似,但它们都需要唯一的 ID 。
答案 0 :(得分: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
提供什么类型的广告?你不能忘记&#34;在编译代码时指定所有泛型类型。
因此,通常这样的事情甚至不会出现。如果用户使用具体类型调用序列化代码,则可以使用相同的具体类型调用反序列化代码。
我想要枚举的行为,但是用户可以灵活地添加自己的结构。
这听起来像是一个特质对象。
另见:
答案 1 :(得分:0)
实现这种想法的最佳方法是限制V的类型,然后使用结构名称作为可能识别模块的类型+字符串的方法。
示例
pub struct Message<V: Serialize + Deserialize> {
key: keytype,
value: V,
crate_path: String
}
然后使用诸如sha之类的东西为结构名称生成一个哈希值,反序列化以检查结构名称。