1use std::collections::HashMap;
2
3use crate::{
4 table::{cell::Cell, Table},
5 utils::multi_lines,
6};
7use anyhow::{Context, Result};
8use serde::{Deserialize, Serialize};
9
10#[derive(Debug, Deserialize, Serialize, Clone)]
11#[serde(untagged)]
12enum Json {
13 Object(serde_json::Map<String, serde_json::Value>),
14 Value(serde_json::Value),
15}
16
17#[derive(Debug, Clone)]
18pub struct Data {
19 data: Vec<Json>,
20 sort_key: Option<String>,
21}
22
23impl Data {
24 fn new(data: Vec<Json>) -> Self {
25 Self {
26 data,
27 sort_key: None,
28 }
29 }
30
31 pub fn from(s: &str) -> Result<Self> {
32 serde_json::from_str::<Vec<Json>>(s)
33 .map(Self::new)
34 .context("unsupported format")
35 }
36
37 pub fn set_sort_key(&mut self, s: Option<String>) -> &mut Self {
38 self.sort_key = s;
39 self
40 }
41
42 fn keys(&self) -> Vec<String> {
43 self.data
44 .get(0)
45 .map(|x| match x {
46 Json::Object(obj) => obj.keys().map(|x| x.clone()).collect(),
47 _ => vec![],
48 })
49 .unwrap_or_default()
50 }
51
52 fn sorted_data(&self) -> Vec<Json> {
53 let sort_keys = self
54 .sort_key
55 .clone()
56 .map(|x| x.split(".").map(String::from).collect::<Vec<_>>());
57
58 if let Some(keys) = sort_keys {
59 let mut data = self.data.clone();
60 data.sort_by_cached_key(|x| {
61 let val = keys.iter().fold(x.clone(), |val, key| match val {
62 Json::Object(obj) => obj
63 .get(key)
64 .map(|v| match v {
65 serde_json::Value::Object(o) => Json::Object(o.clone()),
66 _ => Json::Value(v.clone()),
67 })
68 .unwrap_or(Json::Value(serde_json::Value::default())),
69 _ => val,
70 });
71
72 match val {
73 Json::Object(_) => String::new(),
74 Json::Value(serde_json::Value::Number(n)) => format!("{: >099}", n),
76 Json::Value(v) => v.to_string(),
77 }
78 });
79 data
80 } else {
81 self.data.clone()
82 }
83 }
84
85 fn value_strings(&self) -> Vec<Vec<String>> {
86 self.sorted_data()
87 .iter()
88 .map(|x| match x {
89 Json::Object(obj) => self
90 .keys()
91 .iter()
92 .map(|k| obj.get(k.as_str()).map(|x| x.clone()))
93 .collect::<Vec<_>>(),
94 Json::Value(serde_json::Value::Array(arr)) => {
95 arr.clone().iter().map(|x| Some(x.clone())).collect()
96 }
97 Json::Value(val) => vec![Some(val.clone())],
98 })
99 .map(|x| {
100 x.iter()
101 .map(|x| match x {
102 Some(serde_json::Value::String(s)) => String::from(s),
103 Some(serde_json::Value::Bool(b)) => b.to_string(),
104 Some(serde_json::Value::Number(n)) => n.to_string(),
105 Some(serde_json::Value::Null) => String::from("null"),
106 None => String::from("undefined"),
107 _ => String::from("..."),
108 })
109 .collect::<Vec<_>>()
110 })
111 .collect::<Vec<_>>()
112 }
113
114 pub fn nested_fields(&self) -> Vec<(String, Self)> {
115 let nested_fields = {
116 let data = self.sorted_data();
117 let filtered_data = data.iter().filter_map(|x| match x {
118 Json::Object(obj) => Some(obj),
119 _ => None,
120 });
121 let nested_fields = filtered_data.map(|x| {
122 x.keys()
123 .zip(x.values())
124 .filter(|(_, x)| match x {
125 serde_json::Value::Object(_) | serde_json::Value::Array(_) => true,
126 _ => false,
127 })
128 .collect::<Vec<_>>()
129 });
130 let mut map: HashMap<String, Vec<serde_json::Value>> = HashMap::new();
131 nested_fields.for_each(|xs| {
132 xs.into_iter().for_each(|(k, v)| {
133 let mut vec = if let Some(vec) = map.get(k) {
134 vec.clone()
135 } else {
136 Vec::new()
137 };
138
139 vec.push(v.clone());
140 map.insert(k.clone(), vec);
141 });
142 });
143 map
144 };
145
146 nested_fields
147 .iter()
148 .map(|(k, v)| {
149 (
150 k.clone(),
151 Self::new(
152 v.iter()
153 .map(|x| match x {
154 serde_json::Value::Object(o) => Json::Object(o.clone()),
155 _ => Json::Value(x.clone()),
156 })
157 .collect(),
158 ),
159 )
160 })
161 .collect()
162 }
163
164 pub fn pick(&self, key: String) -> Result<Self> {
165 let keys = key.split(".").collect::<Vec<_>>();
166 let data = self
167 .data
168 .iter()
169 .filter_map(|x| match x {
170 Json::Object(obj) => {
171 let (&head, tail) = keys.split_first()?;
172 let init = obj.get(head)?;
173 tail.iter().try_fold(init, |acc, &x| match acc {
174 serde_json::Value::Object(obj) => obj.get(x),
175 _ => None,
176 })
177 }
178 _ => None,
179 })
180 .map(|x| match x {
181 serde_json::Value::Object(obj) => Json::Object(obj.clone()),
182 _ => Json::Value(x.clone()),
183 })
184 .collect::<Vec<_>>();
185
186 if data.is_empty() {
187 return Err(anyhow::Error::msg(format!("{} is not found", key)));
188 }
189
190 Ok(Self::new(data))
191 }
192}
193
194impl Into<Table<String>> for Data {
195 fn into(self) -> Table<String> {
196 let mut table = Table::new();
197 let keys = self.keys();
198 let values = multi_lines(self.value_strings());
199
200 if !keys.is_empty() {
201 let title = keys.into_iter().map(|x| Cell::new(x)).collect::<Vec<_>>();
202 table.set_header(Some(title));
203 }
204 values
205 .into_iter()
206 .map(|xs| xs.into_iter().map(Cell::new).collect::<Vec<_>>())
207 .for_each(|row| table.push_row(row));
208
209 table
210 }
211}