rust - 我可以相信两个相同结构的序列化是相同的吗?

标签 rust serde

考虑以下代码:

use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize)]
struct MyStruct {
   a: u32,
   b: u32
}

#[derive(Serialize, Deserialize)]
#[serde(rename = "MyStruct")]
struct AlsoMyStruct {
   a: u32,
   b: u32
}

我想知道我是否可以安全地执行以下操作:

let ser = any_encoding::serialize(&MyStruct{a: 33, b: 44}).unwrap();
let deser: AlsoMyStruct = any_encoding::deserialize(&ser).unwrap();

其中 any_encoding 是例如 bincodejson 或任何其他 Serde 支持的编码。在我看来,这应该很好地工作:两个结构具有相同的名称(我明确地将 AlsoMyStruct 重命名为 "MyStruct")和完全相同的字段:相同的字段名称、相同的字段类型、相同的字段顺序。

但是,我想知道:这实际上保证有效吗?或者 Serde 序列化器/反序列化器是否可能在 MyStruct/AlsoMyStruct 的表示中包含一些其他的、极端情况的、可能与平台相关的、不可预见的信息导致两种表示不兼容?

最佳答案

一般来说,不,你不能指望这能起作用。原因是 Serde 和任何反序列化器都不能保证您可以往返数据( source )。这意味着如果您在两个地方使用相同的结构,您甚至不能指望它在所有情况下都有效。

例如 JSON 无法往返 Option<()>像 bincode 这样非自描述的格式不支持未标记的枚举。 类型签名中没有任何内容强制往返。
以下是反序列化可能失败的一些原因:

  • 使用skip_serializing_none具有非自描述格式( serde #1732 )。
  • 任何调用deserialize_any的东西,例如未标记、相邻标记或内部标记的枚举 ( serde #1762 )。
  • 反序列化期间借用,例如 &'de str&'de [u8]serde_json仅支持&'de str如果没有转义序列并且从不支持 &'de [u8] .
  • 某些格式无法序列化某些类型,例如 JSON 不支持结构体作为映射键,而 bincode 仅支持已知长度的序列 ( bincode #167 )。
  • 类型仅实现其中一个特征 ( Serializer/Deserializer ) 或实现不匹配,例如序列化为数字但反序列化为字符串。

话虽这么说,这在某些情况下可以工作。结构体应具有相同的名称和相同顺序的字段。类型或者更确切地说 Serialize/Deserialize实现还需要支持往返。与Option<()>从上面来看,它还取决于 Serializer/Deserializer实现,如果你可以往返它们,即使 Serialize/Deserialize实现确实支持它。

许多类型确实尝试支持往返,因为这是最常见的期望。

关于rust - 我可以相信两个相同结构的序列化是相同的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69120880/

相关文章:

rust - Rust 中的隐式借用

rust - impl block 不需要泛型参数的生命周期限制

rust - 在长时间运行的Rust线程中引用self

rust - 如何在不克隆的情况下获取对可变单例内部数据的引用?

rust - 为什么没有为明确实现的类型实现特征?

rust - 当 Foobar 只有一个字段时,直接反序列化一个 Vec<Foobar<T>> 为 Vec<T>

xml - 解析文件返回错误 "thread ' main' paniced"

rust - 通过 Rust FFI 更改 C 数组元素

rust - 如何使用 Serde 反序列化 parking_lot::Mutex?

json - 如何通过属性将 JSON 对象数组整理成包含每个对象属性向量的结构?