clickhouse_format/output/
json_compact.rs1use core::marker::PhantomData;
2use std::collections::HashMap;
3
4use serde::de::DeserializeOwned;
5use serde_json::{Map, Value};
6
7use crate::format_name::FormatName;
8
9use super::{
10 json::{JsonData, JsonDataInfo},
11 Output, OutputResult,
12};
13
14pub struct JsonCompactOutput<T> {
15 phantom: PhantomData<T>,
16}
17impl<T> Default for JsonCompactOutput<T> {
18 fn default() -> Self {
19 Self::new()
20 }
21}
22impl<T> JsonCompactOutput<T> {
23 pub fn new() -> Self {
24 Self {
25 phantom: PhantomData,
26 }
27 }
28}
29pub type GeneralJsonCompactOutput = JsonCompactOutput<HashMap<String, Value>>;
30
31impl<T> Output for JsonCompactOutput<T>
32where
33 T: DeserializeOwned,
34{
35 type Row = T;
36 type Info = JsonDataInfo;
37
38 type Error = serde_json::Error;
39
40 fn format_name() -> FormatName {
41 FormatName::JsonCompact
42 }
43
44 fn deserialize(&self, slice: &[u8]) -> OutputResult<Self::Row, Self::Info, Self::Error> {
45 self.deserialize_with::<Value>(slice)
46 }
47}
48
49impl<T> JsonCompactOutput<T>
50where
51 T: DeserializeOwned,
52{
53 pub(crate) fn deserialize_with<V>(
54 &self,
55 slice: &[u8],
56 ) -> OutputResult<<Self as Output>::Row, <Self as Output>::Info, <Self as Output>::Error>
57 where
58 V: DeserializeOwned + Into<Value>,
59 {
60 let json_data_tmp: JsonData<Vec<V>> = serde_json::from_slice(slice)?;
61
62 let keys: Vec<_> = json_data_tmp
63 .meta
64 .iter()
65 .map(|x| x.name.to_owned())
66 .collect();
67 let mut data: Vec<T> = vec![];
68 for values in json_data_tmp.data.into_iter() {
69 let map: Map<_, _> = keys
70 .iter()
71 .zip(values)
72 .map(|(k, v)| (k.to_owned(), v.into()))
73 .collect();
74 data.push(serde_json::from_value(Value::Object(map))?);
75 }
76
77 Ok((
78 data,
79 JsonDataInfo {
80 meta: json_data_tmp.meta,
81 rows: json_data_tmp.rows,
82 statistics: json_data_tmp.statistics,
83 },
84 ))
85 }
86}
87
88#[cfg(test)]
89mod tests {
90 use super::*;
91
92 use std::{fs, path::PathBuf};
93
94 use crate::test_helpers::{TestRow, TEST_ROW_1};
95
96 #[test]
97 fn simple() -> Result<(), Box<dyn std::error::Error>> {
98 let file_path = PathBuf::new().join("tests/files/JSONCompact.json");
99 let content = fs::read_to_string(&file_path)?;
100
101 assert_eq!(
102 GeneralJsonCompactOutput::format_name(),
103 file_path
104 .file_stem()
105 .unwrap()
106 .to_string_lossy()
107 .parse()
108 .unwrap()
109 );
110
111 let (rows, info) = GeneralJsonCompactOutput::new().deserialize(content.as_bytes())?;
112 assert_eq!(
113 rows.first().unwrap().get("tuple1").unwrap(),
114 &Value::Array(vec![1.into(), "a".into()])
115 );
116 assert_eq!(info.rows, 2);
117
118 let (rows, info) = JsonCompactOutput::<TestRow>::new().deserialize(content.as_bytes())?;
119 assert_eq!(rows.first().unwrap(), &*TEST_ROW_1);
120 assert_eq!(info.rows, 2);
121
122 Ok(())
123 }
124}