Skip to main content

teaql_tool_std/
json.rs

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            // Very naive way, json_patch provides add but pointer_mut requires path to exist
35            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}