clickhouse_format/input/
json_compact_each_row.rs1use 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}