clickhouse_format/output/
json.rs

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