当前位置:  开发笔记 > 后端 > 正文

用serde_json编码迭代器的惯用方式是什么?

如何解决《用serde_json编码迭代器的惯用方式是什么?》经验,为你挑选了1个好方法。

我想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());
}

Shepmaster.. 5

排水迭代器是一个有趣的野兽。它们允许您分块集合的一部分,获得集合中某些(但不一定是全部)项目的所有权。它们还允许您以合理有效的方式执行此操作。例如,一个矢量可以移动所述后数据集体与单个memcpy

但是,serde本机不支持序列化迭代器(出于充分的原因,请继续阅读)。您可以查看Serialize特征以查看它支持的事物的类型。

您必须自己实现:

use serde::{Deserialize, Serialize}; // 1.0.101
use std::{cell::RefCell, vec};

struct DrainIteratorAdapter<'a, T>(RefCell>);

impl<'a, T: 'a> serde::Serialize for DrainIteratorAdapter<'a, T>
where
    T: serde::Serialize,
{
    fn serialize(&self, serializer: S) -> Result
    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特性的问题。因为我们自己没有serde::Serializevec::Drain,我们必须创建一个NEWTYPE放置于实现。

我们可以将这种解决方案推广到任何迭代器。在我看来,这使它读起来更好看:

use serde::{Deserialize, Serialize}; // 1.0.101
use std::cell::RefCell;

struct IteratorAdapter(RefCell);

impl IteratorAdapter {
    fn new(iterator: I) -> Self {
        Self(RefCell::new(iterator))
    }
}

impl serde::Serialize for IteratorAdapter
where
    I: Iterator,
    I::Item: serde::Serialize,
{
    fn serialize(&self, serializer: S) -> Result
    where
        S: serde::Serializer,
    {
        serializer.collect_seq(self.0.borrow_mut().by_ref())
    }
}

该解决方案的缺点是什么?两次序列化相同的值会产生不同的结果!如果我们简单地序列化并打印两次,就可以得到:

use serde::{Deserialize, Serialize}; // 1.0.101
use std::{cell::RefCell, vec};

struct DrainIteratorAdapter<'a, T>(RefCell>);

impl<'a, T: 'a> serde::Serialize for DrainIteratorAdapter<'a, T>
where
    T: serde::Serialize,
{
    fn serialize(&self, serializer: S) -> Result
    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());
}

这是因为迭代器是短暂的野兽-一旦它们读取一个值,它就消失了!这是一个不错的陷阱,等待您陷入困境。


在您的示例中,这一切都没有道理。您可以访问整个Vec,因此您最好在那时对其进行序列化(或其一部分)。此外,没有理由(现在)购买drain整个系列。那等同于打电话给into_iter



1> Shepmaster..:

排水迭代器是一个有趣的野兽。它们允许您分块集合的一部分,获得集合中某些(但不一定是全部)项目的所有权。它们还允许您以合理有效的方式执行此操作。例如,一个矢量可以移动所述后数据集体与单个memcpy

但是,serde本机不支持序列化迭代器(出于充分的原因,请继续阅读)。您可以查看Serialize特征以查看它支持的事物的类型。

您必须自己实现:

use serde::{Deserialize, Serialize}; // 1.0.101
use std::{cell::RefCell, vec};

struct DrainIteratorAdapter<'a, T>(RefCell>);

impl<'a, T: 'a> serde::Serialize for DrainIteratorAdapter<'a, T>
where
    T: serde::Serialize,
{
    fn serialize(&self, serializer: S) -> Result
    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特性的问题。因为我们自己没有serde::Serializevec::Drain,我们必须创建一个NEWTYPE放置于实现。

我们可以将这种解决方案推广到任何迭代器。在我看来,这使它读起来更好看:

use serde::{Deserialize, Serialize}; // 1.0.101
use std::cell::RefCell;

struct IteratorAdapter(RefCell);

impl IteratorAdapter {
    fn new(iterator: I) -> Self {
        Self(RefCell::new(iterator))
    }
}

impl serde::Serialize for IteratorAdapter
where
    I: Iterator,
    I::Item: serde::Serialize,
{
    fn serialize(&self, serializer: S) -> Result
    where
        S: serde::Serializer,
    {
        serializer.collect_seq(self.0.borrow_mut().by_ref())
    }
}

该解决方案的缺点是什么?两次序列化相同的值会产生不同的结果!如果我们简单地序列化并打印两次,就可以得到:

use serde::{Deserialize, Serialize}; // 1.0.101
use std::{cell::RefCell, vec};

struct DrainIteratorAdapter<'a, T>(RefCell>);

impl<'a, T: 'a> serde::Serialize for DrainIteratorAdapter<'a, T>
where
    T: serde::Serialize,
{
    fn serialize(&self, serializer: S) -> Result
    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());
}

这是因为迭代器是短暂的野兽-一旦它们读取一个值,它就消失了!这是一个不错的陷阱,等待您陷入困境。


在您的示例中,这一切都没有道理。您可以访问整个Vec,因此您最好在那时对其进行序列化(或其一部分)。此外,没有理由(现在)购买drain整个系列。那等同于打电话给into_iter

推荐阅读
手机用户2502852037
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有