1use json_patch::{Patch, diff, patch};
2use serde_json::{Value, from_str};
3use teaql_tool_core::{Result, TeaQLToolError};
4
5pub struct JsonTool;
6
7impl JsonTool {
8 pub fn new() -> Self {
9 Self
10 }
11
12 pub fn parse(&self, s: &str) -> Result<Value> {
13 from_str(s).map_err(|e| TeaQLToolError::ParseError(e.to_string()))
14 }
15
16 pub fn stringify(&self, v: &Value) -> Result<String> {
17 serde_json::to_string(v).map_err(|e| TeaQLToolError::ParseError(e.to_string()))
18 }
19
20 pub fn stringify_pretty(&self, v: &Value) -> Result<String> {
21 serde_json::to_string_pretty(v).map_err(|e| TeaQLToolError::ParseError(e.to_string()))
22 }
23
24 pub fn get<'a>(&self, v: &'a Value, pointer: &str) -> Option<&'a Value> {
25 v.pointer(pointer)
26 }
27
28 pub fn set(&self, v: &mut Value, pointer: &str, value: Value) -> Result<()> {
29 let ptr = v.pointer_mut(pointer);
30 if let Some(target) = ptr {
31 *target = value;
32 Ok(())
33 } else {
34 let p = format!(
36 r#"[{{"op": "add", "path": "{}", "value": {}}}]"#,
37 pointer, value
38 );
39 let patch_obj = serde_json::from_str::<Patch>(&p).unwrap();
40 self.patch(v, &patch_obj)
41 }
42 }
43
44 pub fn remove(&self, v: &mut Value, pointer: &str) -> Result<()> {
45 let p = format!(r#"[{{"op": "remove", "path": "{}"}}]"#, pointer);
46 let patch_obj = serde_json::from_str::<Patch>(&p).unwrap();
47 self.patch(v, &patch_obj)
48 }
49
50 pub fn has(&self, v: &Value, pointer: &str) -> bool {
51 v.pointer(pointer).is_some()
52 }
53
54 pub fn merge(&self, a: &Value, b: &Value) -> Value {
55 let mut result = a.clone();
56 if let (Value::Object(r), Value::Object(b_obj)) = (&mut result, b) {
57 for (k, v) in b_obj {
58 r.insert(k.clone(), v.clone());
59 }
60 }
61 result
62 }
63
64 pub fn diff(&self, a: &Value, b: &Value) -> Patch {
65 diff(a, b)
66 }
67
68 pub fn patch(&self, v: &mut Value, p: &Patch) -> Result<()> {
69 patch(v, p).map_err(|e| TeaQLToolError::ExecutionError(e.to_string()))
70 }
71}
72
73impl Default for JsonTool {
74 fn default() -> Self {
75 Self::new()
76 }
77}