rs_jsonl2x/
lib.rs

1use rust_xlsxwriter::{Workbook, XlsxError};
2use serde_json::Value;
3use std::io::BufRead;
4
5#[derive(Debug)]
6pub enum Error {
7    Io(std::io::Error),
8    Json(serde_json::Error),
9    Xlsx(XlsxError),
10}
11
12impl From<std::io::Error> for Error {
13    fn from(err: std::io::Error) -> Self {
14        Error::Io(err)
15    }
16}
17
18impl From<serde_json::Error> for Error {
19    fn from(err: serde_json::Error) -> Self {
20        Error::Json(err)
21    }
22}
23
24impl From<XlsxError> for Error {
25    fn from(err: XlsxError) -> Self {
26        Error::Xlsx(err)
27    }
28}
29
30impl std::fmt::Display for Error {
31    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
32        match self {
33            Error::Io(err) => write!(f, "IO error: {}", err),
34            Error::Json(err) => write!(f, "JSON error: {}", err),
35            Error::Xlsx(err) => write!(f, "XLSX error: {}", err),
36        }
37    }
38}
39
40pub fn run<R: BufRead>(reader: R, output: &str, sheet: &str, row_limit: u32) -> Result<(), Error> {
41    let mut json_data: Vec<Value> = Vec::new();
42
43    for line in reader.lines().take(row_limit as usize) {
44        let line = line?;
45        let value: Value = serde_json::from_str(&line)?;
46        json_data.push(value);
47    }
48
49    if json_data.is_empty() {
50        println!("No JSON data to write to Excel.");
51        return Ok(());
52    }
53
54    let mut headers: Vec<String> = Vec::new();
55    if let Some(obj) = json_data.first().and_then(|v| v.as_object()) {
56        for key in obj.keys() {
57            headers.push(key.clone());
58        }
59    }
60
61    let mut workbook = Workbook::new();
62    let worksheet = workbook.add_worksheet().set_name(sheet)?;
63
64    // Write headers
65    for (col_num, header) in headers.iter().enumerate() {
66        worksheet.write_string(0, col_num as u16, header)?;
67    }
68
69    // Write data
70    for (row_num, json_obj) in json_data.iter().enumerate() {
71        if let Some(obj) = json_obj.as_object() {
72            for (col_num, header) in headers.iter().enumerate() {
73                if let Some(value) = obj.get(header) {
74                    match value {
75                        Value::String(s) => {
76                            worksheet.write_string((row_num + 1) as u32, col_num as u16, s)?;
77                        }
78                        Value::Number(n) => {
79                            if let Some(f) = n.as_f64() {
80                                worksheet.write_number((row_num + 1) as u32, col_num as u16, f)?;
81                            } else if let Some(i) = n.as_i64() {
82                                worksheet.write_number(
83                                    (row_num + 1) as u32,
84                                    col_num as u16,
85                                    i as f64,
86                                )?;
87                            } else {
88                                worksheet.write_string(
89                                    (row_num + 1) as u32,
90                                    col_num as u16,
91                                    n.to_string(),
92                                )?;
93                            }
94                        }
95                        Value::Bool(b) => {
96                            worksheet.write_boolean((row_num + 1) as u32, col_num as u16, *b)?;
97                        }
98                        Value::Null => {
99                            // Write empty string or leave blank
100                            worksheet.write_string((row_num + 1) as u32, col_num as u16, "")?;
101                        }
102                        _ => {
103                            // For Array, Object, etc., write their string representation
104                            worksheet.write_string(
105                                (row_num + 1) as u32,
106                                col_num as u16,
107                                value.to_string(),
108                            )?;
109                        }
110                    }
111                }
112            }
113        }
114    }
115
116    workbook.save(output)?;
117
118    Ok(())
119}