用 serde_json 编码迭代器的惯用方法是什么?
What is the idiomatic way to encode an iterator with serde_json?
我正在尝试在 Rust 中 drain()
一个 vec
并将结果编码为 JSON 字符串。执行此操作的最佳惯用方法是什么?
#![feature(custom_derive, plugin)]
#![plugin(serde_macros)]
extern crate serde;
extern crate serde_json;
#[derive(Serialize, Deserialize, Debug)]
struct Point {
x: i32,
y: i32,
}
impl Point {
pub fn new(x: i32, y: i32) -> Point {
Point {
x: x,
y: y
}
}
}
fn main() {
let mut points = vec![Point::new(1,2), Point::new(-2,-1), Point::new(0, 0)];
let mut drain = points.drain(..);
println!("{}", serde_json::to_string(&drain).unwrap());
}
排空迭代器是一个有趣的野兽。它们允许您将集合的一部分分块,获得集合中一些但不一定是所有项目的所有权。它们还允许您以合理有效的方式执行此操作。例如,一个矢量可以用单个 memcpy
.
移动尾随数据 整体
但是,serde 本身并不支持序列化迭代器(有充分的理由,请继续阅读)。您可以查看 Serialize
trait 以了解它支持的事物类型。
您必须自己实施:
use serde::{Deserialize, Serialize}; // 1.0.101
use std::{cell::RefCell, vec};
struct DrainIteratorAdapter<'a, T>(RefCell<vec::Drain<'a, T>>);
impl<'a, T: 'a> serde::Serialize for DrainIteratorAdapter<'a, T>
where
T: serde::Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.collect_seq(self.0.borrow_mut().by_ref())
}
}
fn main() {
let mut points = vec![Point::new(1, 2), Point::new(-2, -1), Point::new(0, 0)];
let adapter = DrainIteratorAdapter(RefCell::new(points.drain(..)));
println!("{}", serde_json::to_string(&adapter).unwrap());
}
核心困难部分是序列化应该没有任何副作用。这是一个非常合理的决定。但是,无论何时在迭代器上调用 next
,都必须对其进行变异以更新状态。要结合这两个不匹配的概念,我们必须使用类似 RefCell
.
的东西
除此之外,只需实施 serde::Serialize
trait。由于我们既不拥有 serde::Serialize
也不拥有 vec::Drain
,因此我们必须创建一个 newtype 来放置实现。
我们可以将此解决方案概括为适用于任何迭代器。在我看来,这恰好使它读起来更好看:
use serde::{Deserialize, Serialize}; // 1.0.101
use std::cell::RefCell;
struct IteratorAdapter<I>(RefCell<I>);
impl<I> IteratorAdapter<I> {
fn new(iterator: I) -> Self {
Self(RefCell::new(iterator))
}
}
impl<I> serde::Serialize for IteratorAdapter<I>
where
I: Iterator,
I::Item: serde::Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.collect_seq(self.0.borrow_mut().by_ref())
}
}
此解决方案的缺点是什么? 序列化同一个值两次有不同的结果!如果我们简单地序列化并打印两次值,我们得到:
[{"x":1,"y":2},{"x":-2,"y":-1},{"x":0,"y":0}]
[]
这是因为迭代器是短暂的野兽 - 一旦它们读取了一个值,它就消失了!这是一个很好的陷阱,等着你掉进去。
在您的示例中,none 这确实是有道理的。您可以访问整个 Vec
,因此您最好在此时序列化它(或它的一部分)。此外,没有理由(现在)drain
整个系列。这相当于只调用 into_iter
.
我正在尝试在 Rust 中 drain()
一个 vec
并将结果编码为 JSON 字符串。执行此操作的最佳惯用方法是什么?
#![feature(custom_derive, plugin)]
#![plugin(serde_macros)]
extern crate serde;
extern crate serde_json;
#[derive(Serialize, Deserialize, Debug)]
struct Point {
x: i32,
y: i32,
}
impl Point {
pub fn new(x: i32, y: i32) -> Point {
Point {
x: x,
y: y
}
}
}
fn main() {
let mut points = vec![Point::new(1,2), Point::new(-2,-1), Point::new(0, 0)];
let mut drain = points.drain(..);
println!("{}", serde_json::to_string(&drain).unwrap());
}
排空迭代器是一个有趣的野兽。它们允许您将集合的一部分分块,获得集合中一些但不一定是所有项目的所有权。它们还允许您以合理有效的方式执行此操作。例如,一个矢量可以用单个 memcpy
.
但是,serde 本身并不支持序列化迭代器(有充分的理由,请继续阅读)。您可以查看 Serialize
trait 以了解它支持的事物类型。
您必须自己实施:
use serde::{Deserialize, Serialize}; // 1.0.101
use std::{cell::RefCell, vec};
struct DrainIteratorAdapter<'a, T>(RefCell<vec::Drain<'a, T>>);
impl<'a, T: 'a> serde::Serialize for DrainIteratorAdapter<'a, T>
where
T: serde::Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.collect_seq(self.0.borrow_mut().by_ref())
}
}
fn main() {
let mut points = vec![Point::new(1, 2), Point::new(-2, -1), Point::new(0, 0)];
let adapter = DrainIteratorAdapter(RefCell::new(points.drain(..)));
println!("{}", serde_json::to_string(&adapter).unwrap());
}
核心困难部分是序列化应该没有任何副作用。这是一个非常合理的决定。但是,无论何时在迭代器上调用 next
,都必须对其进行变异以更新状态。要结合这两个不匹配的概念,我们必须使用类似 RefCell
.
除此之外,只需实施 serde::Serialize
trait。由于我们既不拥有 serde::Serialize
也不拥有 vec::Drain
,因此我们必须创建一个 newtype 来放置实现。
我们可以将此解决方案概括为适用于任何迭代器。在我看来,这恰好使它读起来更好看:
use serde::{Deserialize, Serialize}; // 1.0.101
use std::cell::RefCell;
struct IteratorAdapter<I>(RefCell<I>);
impl<I> IteratorAdapter<I> {
fn new(iterator: I) -> Self {
Self(RefCell::new(iterator))
}
}
impl<I> serde::Serialize for IteratorAdapter<I>
where
I: Iterator,
I::Item: serde::Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.collect_seq(self.0.borrow_mut().by_ref())
}
}
此解决方案的缺点是什么? 序列化同一个值两次有不同的结果!如果我们简单地序列化并打印两次值,我们得到:
[{"x":1,"y":2},{"x":-2,"y":-1},{"x":0,"y":0}]
[]
这是因为迭代器是短暂的野兽 - 一旦它们读取了一个值,它就消失了!这是一个很好的陷阱,等着你掉进去。
在您的示例中,none 这确实是有道理的。您可以访问整个 Vec
,因此您最好在此时序列化它(或它的一部分)。此外,没有理由(现在)drain
整个系列。这相当于只调用 into_iter
.