dev_kit/command/json/
mod.rs

1use crate::command::http_parser::HttpRequest;
2use derive_more::Display;
3use std::fs;
4use std::path::PathBuf;
5use std::sync::Arc;
6use strum::EnumIter;
7
8#[derive(clap::Subcommand)]
9pub enum JsonCommand {
10    #[clap(about = "json format, alias 'beauty(b)/query(q)/search(s)/format(f)'", aliases = ["b", "query", "q", "search", "s", "format", "f"])]
11    Beauty {
12        #[arg(help = "json input, support string, file-path, url, cmd", default_value = "")]
13        json: Json,
14        #[arg(short, long, help = "json query to extract")]
15        query: Option<String>,
16        #[arg(long, help = "json query type, alias `qt`, jsonpath(jp)/prefix(p)/suffix(s)/contains(c)/regex(r), and will auto detect if not set", alias = "qt")]
17        query_type: Option<QueryType>,
18        #[arg(long, help = "beauty output", alias = "format", default_value = "true")]
19        beauty: bool,
20        #[arg(short, long, help = "file to write output")]
21        file: Option<PathBuf>,
22    },
23    #[clap(about = "json diff with left and right, alias 'd'", aliases=["d"])]
24    Diff {
25        #[arg(help = "json input, support string, file-path, url, cmd", default_value = "")]
26        left: Json,
27        #[arg(help = "json input, support string, file-path, url, cmd", default_value = "")]
28        right: Json,
29        #[arg(short, long, help = "json path to extract")]
30        query: Option<String>,
31        #[arg(long, help = "json query type, alias `qt`, jsonpath(jp)/prefix(p)/suffix(s)/contains(c)/regex(r), and will auto detect if not set", alias = "qt")]
32        query_type: Option<QueryType>,
33        #[arg(long, help = "diff tool to use, alias dt, support idea/zed/vscode, and will auto detect if not set", alias = "dt")]
34        diff_tool: Option<DiffTool>,
35    },
36}
37
38impl super::Command for JsonCommand {
39    fn run(&self) -> crate::Result<()> {
40        match self {
41            JsonCommand::Beauty { json, query, query_type, beauty, file } => {
42                let content = json.query(query.as_deref(), *query_type, *beauty)?;
43                if let Some(file) = file {
44                    fs::write(&file, content)?;
45                    println!("write to {}", file.display());
46                } else {
47                    println!("{content}");
48                }
49                Ok(())
50            }
51            JsonCommand::Diff { left, right, query, query_type, diff_tool } => {
52                let _ = left.diff(right, query.as_deref(), *query_type, diff_tool.map(|it| it))?;
53                Ok(())
54            }
55        }
56    }
57}
58
59#[derive(Debug, Clone, Display, )]
60pub enum Json {
61    #[display("{_0}")]
62    Cmd(String),
63    #[display("{_0}")]
64    HttpRequest(HttpRequest),
65    #[display("{}", _0.display())]
66    Path(PathBuf),
67    #[display("{_0}")]
68    String(String),
69    #[display("{}", _0.to_string())]
70    JsonValue(Arc<serde_json::Value>),
71}
72
73#[derive(Debug, Clone, Copy)]
74pub enum QueryType {
75    JsonPath,
76    KeyPattern(KeyPatternType),
77}
78
79impl Default for QueryType {
80    fn default() -> Self {
81        Self::KeyPattern(KeyPatternType::default())
82    }
83}
84
85#[derive(Debug, Clone, Copy, Default)]
86pub enum KeyPatternType {
87    Prefix,
88    Suffix,
89    #[default]
90    Contains,
91    Regex,
92}
93
94mod type_;
95mod json;
96
97#[derive(Debug, Copy, Clone, Display, EnumIter)]
98pub enum DiffTool {
99    #[display("{_0}")]
100    JetbrainsIDE(JetbrainsIDE),
101    #[display("zed")]
102    Zed,
103    #[display("vscode")]
104    VSCode,
105}
106
107mod difftool;
108
109#[derive(Debug, Copy, Clone, Display, EnumIter, Default)]
110#[display(rename_all = "lowercase")]
111pub enum JetbrainsIDE {
112    #[default]
113    Idea,
114    CLion,
115    RustRover,
116    GoLand,
117    PyCharm,
118    WebStorm,
119    Rider,
120    DataGrip,
121    AppCode,
122}
123
124#[cfg(test)]
125mod tests {
126    #[test]
127    fn test() -> crate::Result<()> {
128        let json1 = r#"{"a":1,"b":2,"c":3}"#;
129        let json1: serde_json::Value = serde_json::from_str(json1)?;
130        let json1 = serde_json::to_string(&json1)?;
131        println!("{}", json1);
132        let json2 = r#"{"c":3,"b":2,"a":1, "d":{"g":"gg","f":"ff","e":"ee"}}"#;
133        let json2: serde_json::Value = serde_json::from_str(json2)?;
134        let json2 = serde_json::to_string(&json2)?;
135        println!("{}", json2);
136        Ok(())
137    }
138}