【问题标题】:Rust: Deserialize a JSON array into a very simple custom tableRust:将 JSON 数组反序列化为一个非常简单的自定义表
【发布时间】:2020-01-23 07:44:55
【问题描述】:

我正在尝试使用serde_json 将数组数组(表示字符串单元格表)反序列化为 Rust 中的自定义结构。我知道使用 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 字符串定义结构?

【问题讨论】:

    标签: rust serde-json


    【解决方案1】:

    您想将标签 #[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);
        }
    
    }
    

    Playground

    #[serde(transparent)]

    序列化和反序列化具有一个字段的新类型结构或大括号结构,就像它的一个字段被自己序列化和反序列化一样。类似于#[repr(transparent)]。

    取自此处的属性页面:https://serde.rs/container-attrs.html

    【讨论】:

    • 是的!但我必须承认,这个解释对我来说不是很“透明”。我需要花更多时间阅读 serde 文档。谢谢!!!
    【解决方案2】:

    您的输入不是有效的 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);
    }
    

    【讨论】:

    • 输入是一个非常有效的 JSON 字符串!问题是 serde 希望找到一个要反序列化为结构的 JSON 对象,在这种情况下,我希望将 JSON array 反序列化为我创建的结构。然后我需要使结构“透明”以反序列化到内部 Vector 字段中。至少我是这么理解的。
    猜你喜欢
    • 2021-06-21
    • 1970-01-01
    • 1970-01-01
    • 2017-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-14
    相关资源
    最近更新 更多