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

Sea*_*s32 3 rust borrowing serde

我有一个这样的结构:

#[derive(Serialize, Deserialize)]
struct Thing {
    pub small_header: Header,
    pub big_body: Body,
}
Run Code Online (Sandbox Code Playgroud)

我想将其序列化Thing以通过网络发送。我已经有一个Body可用的但我无法移动它(想象一下我正在用它做某事,我不时收到一个命令来暂时停止我正在做的事情并发送我现在拥有的任何数据)并且我可以不要复制它(它太大了,可能有数百兆字节)。

所以我希望 Serde 只借用我所拥有的序列化它,因为它不需要为此移动到结构中。如果我重写Thing拿个参考,我显然推不出来Deserialize

我一直在使用的解决方法是Arc<Body>在我的代码中使用一个,这样我就可以在我的正常逻辑中使用主体,当我需要序列化它时,我可以做一个廉价的克隆并将其Arc<Body>放入结构中进行序列化. 在反序列化期间,Serde 将创建Arc一个引用计数为 1的新对象。

这仍然涉及散布Arc在我的代码中,这不是很好,更不用说不必要的(尽管很小)运行时成本。此用例的正确解决方案是什么?

有趣的是,如果我不必发送标头,那么这将不是问题,因为我可以按引用序列化并按值反序列化,但是标头的存在使这变得不可能。我觉得我错过了一些关于 Serde 如何在这里借用数据的信息......

dto*_*nay 5

您可以使用 a Cow,它将Cow::Borrowed在序列化时使用,并且Cow::Owned在反序列化时反序列化。

use std::borrow::Cow;

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

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

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

#[derive(Deserialize)]
struct DeserializeThing {
    small_header: Header,
    big_body: Body,
}
Run Code Online (Sandbox Code Playgroud)