如何借用一个字段进行序列化,但在反序列化期间创建它?

5

我有一个这样的结构体:

#[derive(Serialize, Deserialize)]
struct Thing {
    pub small_header: Header,
    pub big_body: Body,
}

我想将这个Thing序列化以便通过网络发送。我已经有了一个可用的Body,但是我不能移动它 (想象一下我正在做某些事情,然后每隔一段时间我就会收到一个命令暂时停止我正在做的事情并发送任何我现在拥有的数据),我也不能复制它 (它太大了,可能有数百兆字节)。
因此,我希望Serde只是借用我正在使用的Body进行序列化,因为它不应该需要移动到结构体中进行操作。如果我重写Thing以获取引用,则显然无法派生Deserialize
我一直在使用的解决方法是在我的代码中使用Arc<Body>,这样我可以在我的正常逻辑中使用body,并且当我需要对其进行序列化时,我可以做一个cheap clone,并将Arc<Body>放入结构体中进行序列化。在反序列化期间,Serde将创建一个新的Arc,其引用计数为1。
这仍然涉及将Arc分散到我的代码中,这并不理想,更不用说不必要的(虽然轻微的)运行时成本了。这种情况下的正确解决方法是什么?
有趣的是,如果我不需要发送头文件,那么这将不是一个问题,因为我可以按引用序列化并按值反序列化,但是头文件的存在使此操作不可能。我觉得我在理解Serde如何借用数据方面有所遗漏...

https://serde.rs/impl-deserializer.html,不太清楚您的问题,请包含当前 [mcve] 的副本。 - Stargateur
2个回答

9

您可以使用Cow,在序列化时它将是Cow::Borrowed,在反序列化时它将变为Cow::Owned

use std::borrow::Cow;

#[derive(Serialize, Deserialize)]
struct Thing<'a> {
    small_header: Header,
    big_body: Cow<'a, Body>,
}

或者,您可以将其序列化和反序列化为两个独立的数据结构。

#[derive(Serialize)]
struct SerializeThing<'a> {
    small_header: Header,
    big_body: &'a Body,
}

#[derive(Deserialize)]
struct DeserializeThing {
    small_header: Header,
    big_body: Body,
}

-1

请记住,serde 总是分配空间(作为默认值)(https://github.com/serde-rs/serde/issues/1852)。

为确保您真正地借用,请使用#[serde(borrow)]。

例如:

#[derive(Serialize, Deserialize)]
struct Thing<'a> {
    small_header: Header,
    #[serde(borrow)]
    big_body: Cow<'a, Body>,
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接