1use serde::Serialize;
10use serde::de::DeserializeOwned;
11
12use crate::error::ParseError;
13
14pub fn parse<T: DeserializeOwned>(text: &str) -> Result<Vec<T>, ParseError> {
17 let mut rows = Vec::new();
18 for (idx, raw) in text.lines().enumerate() {
19 let line = idx + 1;
20 let trimmed = raw.trim();
21 if trimmed.is_empty() {
22 continue;
23 }
24 let row: T = serde_json::from_str(trimmed).map_err(|e| ParseError {
25 line,
26 message: e.to_string(),
27 })?;
28 rows.push(row);
29 }
30 Ok(rows)
31}
32
33pub fn serialize<T: Serialize>(rows: &[T]) -> Result<String, serde_json::Error> {
35 let mut out = String::new();
36 for row in rows {
37 out.push_str(&serde_json::to_string(row)?);
38 out.push('\n');
39 }
40 Ok(out)
41}
42
43#[cfg(test)]
44mod tests {
45 use serde::Deserialize;
46
47 use super::*;
48
49 #[derive(Debug, PartialEq, Serialize, Deserialize)]
50 struct Row {
51 name: String,
52 }
53
54 #[test]
55 fn blank_lines_are_skipped() {
56 let rows: Vec<Row> = parse("{\"name\":\"a\"}\n\n \n{\"name\":\"b\"}\n").unwrap();
57 assert_eq!(rows.len(), 2);
58 assert_eq!(rows[1].name, "b");
59 }
60
61 #[test]
62 fn parse_reports_the_offending_line() {
63 let err = parse::<Row>("{\"name\":\"a\"}\nnot json\n").unwrap_err();
64 assert_eq!(err.line, 2);
65 }
66
67 #[test]
68 fn serialize_terminates_every_row() {
69 let text = serialize(&[Row { name: "a".into() }, Row { name: "b".into() }]).unwrap();
70 assert_eq!(text, "{\"name\":\"a\"}\n{\"name\":\"b\"}\n");
71 }
72
73 #[test]
74 fn empty_rows_serialize_to_empty_text() {
75 assert_eq!(serialize::<Row>(&[]).unwrap(), "");
76 }
77}