Rust: десериализация массива JSON в очень простую пользовательскую таблицу - PullRequest
1 голос
/ 23 января 2020

Я пытаюсь десериализовать массив массивов (представляет таблицу строковых ячеек) в пользовательскую структуру в Rust с serde_ json. Я знаю, что использования serde_json::Value достаточно для этого простого случая, но я хотел бы создать собственный тип.

use serde::{Deserialize};
use serde_json::{self, Result};

#[derive(Deserialize, Debug)]
pub struct Row {
    pub cells: Vec<String>,
}

#[derive(Deserialize, Debug)]
pub struct Table {
    pub rows: Vec<Row>,
}

impl Table {

    pub fn new(data: &str) -> Result<Table> {
        let table = serde_json::from_str(data);
        table
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn from_json_string() {
        let test_table = r#"
[
  ["0,1", "0,2", "0,3"], 
  ["1,1", "1,2", "1,3"]
]
"#;
        let table: Table = Table::new(&test_table).unwrap();
        assert_eq!(table.rows.len(), 2);
    }

}

С этим кодом тест паникует с Error("invalid type: string \"0,1\", expected struct Row".

Как мне определить структуры для этой простой JSON строки?

Ответы [ 2 ]

2 голосов
/ 23 января 2020

Вы хотите добавить тег #[serde(transparent)] к структурам

use serde::{Deserialize};
use serde_json::{self, Result};

#[derive(Deserialize, Debug)]
#[serde(transparent)] 
pub struct Row {
    pub cells: Vec<String>,
}

#[derive(Deserialize, Debug)]
#[serde(transparent)] 
pub struct Table {
    pub rows: Vec<Row>,
}

impl Table {

    pub fn new(data: &str) -> Result<Table> {
        let table = serde_json::from_str(data);
        table
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn from_json_string() {
        let test_table = r#"
[
  ["0,1", "0,2", "0,3"], 
  ["1,1", "1,2", "1,3"]
]
"#;
        let table: Table = Table::new(&test_table).unwrap();
        assert_eq!(table.rows.len(), 2);
    }

}

Детская площадка

#[serde(transparent)]

Сериализация и десериализовать структуру нового типа или фигурную структуру с одним полем, точно таким же, как если бы его одно поле было сериализовано и десериализовано само по себе. Аналог # [repr (прозрачный)].

Взят со страницы атрибутов здесь: https://serde.rs/container-attrs.html

0 голосов
/ 23 января 2020

Ваш ввод не является допустимым JSON, и поскольку вы используете serde_json, было бы разумно, чтобы ввод был действительно JSON.

. Вы можете изменить свой код на что-то похожее на код ниже:

#[test]
fn from_json_string() {
    let test_table = r#"
    {
        "rows" : [
            {
                "cells" : ["1", "2"]
            },
            {
                "cells" : ["3", "4"]
            }
        ]
    }"#;

    let table: Table = Table::new(&test_table).unwrap();
    assert_eq!(table.rows.len(), 2);
}
...