【发布时间】:2021-11-29 12:01:02
【问题描述】:
我正在尝试处理来自通道的数据,因此无法一次序列化整个结构。事实上,它不会都适合记忆。我遇到的问题是我无法创建Option<SerializeSeq>,因为该对象依赖于Serializer(它的寿命不够长)。我想一起初始化它们,或者根本不初始化:
use serde::ser::{SerializeSeq, Serializer};
fn process_stream(output: bool) -> serde_json::Result<()> {
let rows = /* whatever iterator */ "serde".chars();
let mut seq = if output {
let out = std::io::stdout();
let mut ser = serde_json::Serializer::new(out);
let seq = ser.serialize_seq(None)?
Some(Ok(seq))
} else {
None
}.transpose()?;
for row in rows {
//process_data(row);
if let Some(seq) = &mut seq {
seq.serialize_element(&row)?;
}
}
if let Some(seq) = seq {
seq.end()?;
}
Ok(())
}
(here的原始代码sn-p。)
问题是:ser does not live long enough。但我不想在外部范围内初始化ser,因为它可能未启用(并且它的编写者会创建或截断不应创建的文件)。我尝试将ser 和seq 作为一个元组返回。我尝试将它们放在一个辅助结构中,但我无法弄清楚所有模板参数和生命周期。
如何根据条件初始化serde序列化器和序列并存储在Option中?
【问题讨论】:
-
不知道你有没有试过,但显而易见的想法是在外部范围内声明
ser,但只在需要时初始化它:play.rust-lang.org/… -
@user4815162342 谢谢,我没有意识到这是允许的!
-
即使不是,您仍然可以使用
let mut ser = None后跟ser = Some(Serializer::new(...))并用作ser.unwrap().serialize_element(&row)来伪造它。那会更难看,因为它需要一个误导性的unwrap(),而实际上可能永远不会触发。 -
@user4815162342 我尝试了类似的方法,包括该代码和使用
map或if let的更惯用的版本。它没有用,但我可能没有完全按照您的想法编写它......这种类型的代码可能会以多种方式失败。除了一个生命周期不够长的变量之外,我不允许使用对局部变量的引用来构造seq。或函数参数。或者可以在借用时丢弃临时的。 -
This is 我的想法。您可以使用对本地的引用来构造
seq,只要它比seq寿命长。在您的实验中,您可能没有使用as_mut(),没有它,unwrap()会将seq移出选项。这导致另一个“活得不够长”的错误,似乎以一种非常令人困惑的方式击败了范围更广的seq。修复是微不足道的,但只有在您了解问题的根源之后。