clickhouse_format/output/
json.rs1use 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}