问题
I'm trying to deserialize an array of arrays (represents a table of string cells) into a custom struct in Rust with serde_json. I know that using serde_json::Value
is enough for this simple case but I would like to construct a custom type.
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);
}
}
With this code, the test panics with Error("invalid type: string \"0,1\", expected struct Row"
.
How should I define the structs for this simple JSON string?
回答1:
You want to add the tag #[serde(transparent)]
to the structs
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)]
Serialize and deserialize a newtype struct or a braced struct with one field exactly the same as if its one field were serialized and deserialized by itself. Analogous to #[repr(transparent)].
Taken from the attributes page here: https://serde.rs/container-attrs.html
回答2:
Your input is not a valid JSON and since you are using serde_json
it would be wise for the input to actually be a JSON.
You can change your code to something similar to code below:
#[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);
}
来源:https://stackoverflow.com/questions/59873674/rust-deserialize-a-json-array-into-a-very-simple-custom-table