clickhouse_format/input/
json_compact_each_row.rs

1use serde::Serialize;
2use serde_json::{ser::CompactFormatter, Serializer};
3
4use crate::{format_name::FormatName, input::Input};
5
6pub struct JsonCompactEachRowInput<T> {
7    rows: Vec<Vec<T>>,
8}
9impl<T> JsonCompactEachRowInput<T> {
10    pub fn new(rows: Vec<Vec<T>>) -> Self {
11        Self { rows }
12    }
13}
14
15impl<T> Input for JsonCompactEachRowInput<T>
16where
17    T: Serialize,
18{
19    type Error = serde_json::Error;
20
21    fn format_name() -> FormatName {
22        FormatName::JsonCompactEachRow
23    }
24
25    fn serialize(&self) -> Result<Vec<u8>, Self::Error> {
26        let mut buf = vec![];
27        let mut ser_buf = Vec::with_capacity(128);
28
29        for row in &self.rows {
30            buf.push(b'[');
31            for (i, item) in row.iter().enumerate() {
32                ser_buf.clear();
33                let mut ser = Serializer::with_formatter(&mut ser_buf, CompactFormatter);
34                item.serialize(&mut ser)?;
35
36                buf.extend_from_slice(ser.into_inner());
37
38                if i < (row.len() - 1) {
39                    buf.extend_from_slice(b", ");
40                }
41            }
42            buf.push(b']');
43
44            buf.push(b'\n');
45        }
46
47        Ok(buf)
48    }
49}
50
51#[cfg(test)]
52mod tests {
53    use super::*;
54
55    use std::{fs, path::PathBuf};
56
57    use crate::test_helpers::{TEST_ROW_1, TEST_ROW_2};
58
59    use serde_json::{Map, Value};
60
61    #[test]
62    fn simple() -> Result<(), Box<dyn std::error::Error>> {
63        let file_path = PathBuf::new().join("tests/files/JSONCompactEachRow.txt");
64        let content = fs::read_to_string(&file_path)?;
65
66        assert_eq!(
67            JsonCompactEachRowInput::<()>::format_name(),
68            file_path
69                .file_stem()
70                .unwrap()
71                .to_string_lossy()
72                .parse()
73                .unwrap()
74        );
75
76        let mut rows: Vec<Vec<Value>> = vec![];
77        rows.push(vec![
78            TEST_ROW_1.array1.to_owned().into(),
79            TEST_ROW_1.array2.to_owned().into(),
80            vec![
81                Value::Number(TEST_ROW_1.tuple1.to_owned().0.into()),
82                Value::String(TEST_ROW_1.tuple1.to_owned().1),
83            ]
84            .into(),
85            vec![
86                Value::Number(TEST_ROW_1.tuple2.to_owned().0.into()),
87                Value::Null,
88            ]
89            .into(),
90            Value::Object(TEST_ROW_1.map1.iter().fold(Map::new(), |mut m, (k, v)| {
91                m.insert(k.to_owned(), Value::String(v.to_owned()));
92                m
93            })),
94        ]);
95        rows.push(vec![
96            TEST_ROW_2.array1.to_owned().into(),
97            TEST_ROW_2.array2.to_owned().into(),
98            vec![
99                Value::Number(TEST_ROW_2.tuple1.to_owned().0.into()),
100                Value::String(TEST_ROW_2.tuple1.to_owned().1),
101            ]
102            .into(),
103            vec![
104                Value::Number(TEST_ROW_2.tuple2.to_owned().0.into()),
105                Value::String(TEST_ROW_2.tuple2.to_owned().1.unwrap()),
106            ]
107            .into(),
108            Value::Object(TEST_ROW_2.map1.iter().fold(Map::new(), |mut m, (k, v)| {
109                m.insert(k.to_owned(), Value::String(v.to_owned()));
110                m
111            })),
112        ]);
113
114        let bytes = JsonCompactEachRowInput::new(rows).serialize()?;
115        assert_eq!(bytes, content.as_bytes());
116
117        Ok(())
118    }
119}