【问题标题】:Serialize a nested array of objects using serde使用 serde 序列化嵌套的对象数组
【发布时间】:2021-09-23 01:16:38
【问题描述】:

从描述拼图网格的结构中,我希望能够序列化嵌套数组:

struct Grid {
  display: String,
  solution: String,
  width: usize,
  height: usize,
}

假设结构为 Grid { display: "????", solution: "1234", width: 2, height: 2 },我希望输出如下所示(以 JSON 格式):

[
  [
    {
      "display": "?",
      "solution": "1"
    },
    {
      "display": "?",
      "solution": "2"
    }
  ],
  [
    {
      "display": "?",
      "solution": "3"
    },
    {
      "display": "?",
      "solution": "4"
    }
  ]
]

我的初始实施草案如下所示:

impl<'a> Serialize for Grid<'a> {
    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        let mut columns = serializer.serialize_seq(Some(self.height))?;
        for column_index in 0..self.height {
            let mut column = columns.serialize_seq(Some(self.width))?;
            for row_index in 0..self.width {
                let mut cell = column.serialize_map(Some(2))?;
                let cell_index = column_index * self.height + row_index;
                cell.serialize_entry("display", self.display.chars().nth(cell_index).unwrap())?;
                cell.serialize_entry("solution", self.solution.chars().nth(cell_index).unwrap())?;

                cell.end()?;
            }

            column.end()?;
        }

        columns.end()
    }
}

但是,SerializeSeq 不会公开另一个 serialize_seq 方法以进行进一步嵌套。如何从一个这样的结构中序列化嵌套数组?

【问题讨论】:

  • 从长远来看,编写自定义序列化程序可能是最好的选择,但我想编写 struct Item { display: String, solution: String } 然后在 Grid 上编写一个方法会很容易(如果效率低下)返回和/或序列化Vec&lt;Vec&lt;Item&gt;&gt;
  • 你也需要第二个结构来实现序列化,最后可能还有第三个

标签: rust serde


【解决方案1】:

具有 displaysolution 作为字段的辅助结构 Cell 将使序列化更容易。然后,您可以使用迭代器适配器(包括来自解决方案的 zipmap)以功能方式构造单元列表,并显示网格的值。然后,使用 chunks 适配器将一维向量按行大小转换为二维向量。最后,使用宏json!生成json字符串。

use serde::{Deserialize, Serialize};
use serde_json::json;

struct Grid {
  display: String,
  solution: String,
  width: usize,
  height: usize,
}

#[derive(Serialize, Deserialize)]
struct Cell {
    display: char,
    solution: char,
}

fn main() {
    let grid = Grid { display: "????".to_string(), solution: "1234".to_string(), width: 2, height: 2 };

    let cells :Vec<Cell> = grid.display.chars().zip(grid.solution.chars()).map(|(a, b)| Cell {display: a, solution: b} ).collect();
    let rows : Vec<&[Cell]>= cells.chunks(grid.width).collect();

    print!("{:#}", json!(rows));
}

playground

【讨论】:

  • 我最终选择了这个解决方案,尽管与没有辅助结构的情况相比,我不能说我对它非常满意。哦,好吧——谢谢你的建议!
【解决方案2】:

您需要几个辅助结构来表示一行和一个单元格:

use serde::*; // 1.0.130
use serde::ser::*;

struct Grid {
  display: String,
  solution: String,
  width: usize,
  height: usize,
}

impl Serialize for Grid {
    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        let mut rows = serializer.serialize_seq (Some (self.height))?;
        for idx in 0..self.height {
            rows.serialize_element (&Row { grid: self, start_idx: idx * self.width })?;
        }
        rows.end()
    }
}

struct Row<'a> {
    grid: &'a Grid,
    start_idx: usize,
}

impl<'a> Serialize for Row<'a> {
    fn serialize<S: Serializer> (&self, serializer: S) -> Result<S::Ok, S::Error> {
        let mut row = serializer.serialize_seq (Some (self.grid.width))?;
        for idx in 0..self.grid.width {
            row.serialize_element (&Cell { grid: self.grid, idx: self.start_idx + idx })?;
        }
        row.end()
    }
}

struct Cell<'a> {
    grid: &'a Grid,
    idx: usize,
}

impl<'a> Serialize for Cell<'a> {
    fn serialize<S: Serializer> (&self, serializer: S) -> Result<S::Ok, S::Error> {
        let mut cell = serializer.serialize_map (Some (2))?;
        cell.serialize_entry ("display", &self.grid.display.chars().nth (self.idx).unwrap())?;
        cell.serialize_entry ("solution", &self.grid.solution.chars().nth (self.idx).unwrap())?;
        cell.end()
    }
}

Playground

【讨论】:

    猜你喜欢
    • 2022-11-10
    • 1970-01-01
    • 1970-01-01
    • 2023-04-05
    • 1970-01-01
    • 1970-01-01
    • 2013-01-07
    • 2020-09-08
    • 1970-01-01
    相关资源
    最近更新 更多