north_common/utils/
serde_utils.rs

1#![allow(dead_code)]
2use serde_json::{Map, Value};
3
4/// Trait used to merge Json Values
5pub trait Merge {
6    /// Method use to merge two Json Values : ValueA <- ValueB.
7    fn merge(&mut self, new_json_value: Value);
8    /// Merge a new value in specific json pointer.
9    fn merge_in(&mut self, json_pointer: &str, new_json_value: Value);
10}
11
12/// function merges two json values into one
13///
14/// # Example
15/// ```
16/// use serde_json::json;
17/// use north_common::utils::serde_utils::merge_json;
18///
19/// let mut a = json!({
20///   "title": "This is a title",
21///   "person" : {
22///      "firstName" : "John",
23///      "lastName" : "Doe"
24///    },
25///    "cities":[ "london", "paris" ]
26///  });
27///
28///  let b = json!({
29///    "title": "This is another title",
30///    "person" : {
31///       "firstName" : "Jane"
32///    },
33///    "cities":[ "colombo" ]
34///  });
35///  merge_json(&mut a, b)
36/// ```
37pub fn merge_json(a: &mut Value, b: Value) {
38    match (a, b) {
39        (a @ &mut Value::Object(_), Value::Object(b)) => {
40            let a = a.as_object_mut().unwrap();
41            for (k, v) in b {
42                merge_json(a.entry(k).or_insert(Value::Null), v);
43            }
44        }
45        (a @ &mut Value::Array(_), Value::Array(b)) => {
46            let a = a.as_array_mut().unwrap();
47            a.extend(b);
48            a.dedup();
49        }
50        (a @ &mut Value::Array(_), Value::Object(b)) => {
51            let a = a.as_array_mut().unwrap();
52            a.push(Value::Object(b));
53            a.dedup();
54        }
55        (a, b) => *a = b,
56    }
57}
58
59/// function merges a yaml string into a json value
60///
61/// usage:
62/// ```rust
63/// use serde_json::json;
64/// use north_common::utils::serde_utils::merge_json_and_yaml;
65/// let mut a = json!({
66///   "title": "This is a title",
67///   "person" : {
68///      "firstName" : "John",
69///      "lastName" : "Doe"
70///    },
71///    "cities":[ "london", "paris" ]
72///  });
73///
74///  let b = r"name: demo";
75///  merge_json_and_yaml(&mut a, b.to_string())
76/// ```
77pub fn merge_json_and_yaml(a: &mut Value, raw_str: String) {
78    let try_json = serde_yaml::from_str::<Value>(&raw_str).unwrap();
79    merge_json(a, try_json)
80}
81
82impl Merge for Value {
83    /// # Examples: Merge two array together.
84    /// ```
85    /// use serde_json::Value;
86    /// use north_common::utils::serde_utils::Merge;
87    ///
88    /// let mut array1: Value = serde_json::from_str(r#"["a","b"]"#).unwrap();
89    /// let array2: Value = serde_json::from_str(r#"["b","c"]"#).unwrap();
90    /// array1.merge(array2);
91    /// assert_eq!(r#"["a","b","c"]"#, array1.to_string());
92    /// ```
93    /// # Examples: Merge two objects together.
94    /// ```
95    /// use serde_json::Value;
96    /// use north_common::utils::serde_utils::Merge;
97    ///
98    /// let mut object1: Value = serde_json::from_str(r#"{"value1":"a","value2":"b"}"#).unwrap();
99    /// let object2: Value = serde_json::from_str(r#"{"value1":"a","value2":"c","value3":"d"}"#).unwrap();
100    /// object1.merge(object2);
101    /// assert_eq!(r#"{"value1":"a","value2":"c","value3":"d"}"#,object1.to_string());
102    /// ```
103    /// # Examples: Merge an object into an array.
104    /// ```
105    /// use serde_json::Value;
106    /// use north_common::utils::serde_utils::Merge;
107    ///
108    /// let mut array: Value = serde_json::from_str(r#"[]"#).unwrap();
109    /// let object: Value = serde_json::from_str(r#"{"field1":"value1"}"#).unwrap();
110    /// array.merge(object);
111    /// assert_eq!(r#"[{"field1":"value1"}]"#,array.to_string());
112    /// ```
113    /// # Examples: Merge an array into an object.
114    /// ```
115    /// use serde_json::Value;
116    /// use north_common::utils::serde_utils::Merge;
117    ///
118    /// let mut object: Value = serde_json::from_str(r#"{"field1":"value1"}"#).unwrap();
119    /// let array: Value = serde_json::from_str(r#"["value2","value3"]"#).unwrap();
120    /// object.merge(array);
121    /// assert_eq!(r#"["value2","value3"]"#,object.to_string());
122    /// ```
123    fn merge(&mut self, new_json_value: Value) {
124        merge(self, &new_json_value);
125    }
126    /// # Examples: Merge an array in an object in a specific position.
127    /// ```
128    /// use serde_json::Value;
129    /// use north_common::utils::serde_utils::Merge;
130    ///
131    /// let mut object: Value = serde_json::from_str(r#"{"my_array":[{"a":"t"}]}"#).unwrap();
132    /// let array: Value = serde_json::from_str(r#"["b","c"]"#).unwrap();
133    /// object.merge_in("/my_array", array.clone());
134    /// assert_eq!(r#"{"my_array":[{"a":"t"},"b","c"]}"#, object.to_string());
135    /// ```
136    /// # Examples: Merge two objects together in a specific position.
137    /// ```
138    /// use serde_json::Value;
139    /// use north_common::utils::serde_utils::Merge;
140    ///
141    /// let mut object1: Value = serde_json::from_str(r#"{"my_array":[{"a":"t"}]}"#).unwrap();
142    /// let object2: Value = serde_json::from_str(r#"{"b":"c"}"#).unwrap();
143    /// object1.merge_in("/my_array/0/a", object2.clone());
144    /// assert_eq!(r#"{"my_array":[{"a":{"b":"c"}}]}"#, object1.to_string());
145    /// ```
146    /// # Examples: Merge an object in an array in a specific position.
147    /// ```
148    /// use serde_json::Value;
149    /// use north_common::utils::serde_utils::Merge;
150    ///
151    /// let mut json_value: Value = serde_json::from_str(r#"[{"array1":[{"field":"value1"}]}]"#).unwrap();
152    /// json_value.merge_in("/other_field", Value::String("value".to_string()));
153    /// assert_eq!(r#"[{"array1":[{"field":"value1"}]},{"other_field":"value"}]"#,json_value.to_string());
154    /// ```
155    // # Examples: Build a new object.
156    // ```
157    // use serde_json::{Map,Value};
158    // use north_common::utils::serde_utils::Merge;
159    //
160    // let mut object: Value = Value::default();
161    // object.merge_in("/field", Value::String("value".to_string()));
162    // object.merge_in("/object", Value::Object(Map::default()));
163    // object.merge_in("/array", Value::Array(Vec::default()));
164    // assert_eq!(r#"{"array":[],"field":"value","object":{}}"#,object.to_string());
165    // ```
166    fn merge_in(&mut self, json_pointer: &str, new_json_value: Value) {
167        let fields: Vec<&str> = json_pointer.split('/').skip(1).collect();
168
169        merge_in(self, fields, new_json_value);
170    }
171}
172
173fn merge(a: &mut Value, b: &Value) {
174    match (a, b) {
175        (&mut Value::Object(ref mut a), Value::Object(b)) => {
176            for (k, v) in b {
177                merge(a.entry(k.clone()).or_insert(Value::Null), v);
178            }
179        }
180        (&mut Value::Array(ref mut a), Value::Array(b)) => {
181            a.extend(b.clone());
182            a.dedup();
183        }
184        (&mut Value::Array(ref mut a), Value::Object(b)) => {
185            a.push(Value::Object(b.clone()));
186            a.dedup();
187        }
188        (a, b) => {
189            *a = b.clone();
190        }
191    }
192}
193
194fn merge_in(json_value: &mut Value, fields: Vec<&str>, new_json_value: Value) {
195    if fields.is_empty() {
196        return json_value.merge(new_json_value);
197    }
198
199    let mut fields = fields.clone();
200    let field = fields.remove(0);
201
202    if field.is_empty() {
203        return json_value.merge(new_json_value);
204    }
205
206    match json_value.pointer_mut(format!("/{}", field).as_str()) {
207        // Find the field and the json_value_targeted.
208        Some(json_targeted) => {
209            if !fields.is_empty() {
210                merge_in(json_targeted, fields, new_json_value);
211            } else {
212                json_targeted.merge(new_json_value);
213            }
214        }
215        // Not find the field and the json_value_targeted.
216        // Add the new field and retry the merge_in with same parameters.
217        None => {
218            let new_value = match field.parse::<usize>().ok() {
219                Some(position) => {
220                    let mut vec = Vec::default();
221                    match vec.get(position) {
222                        Some(_) => vec.insert(position, Value::default()),
223                        None => vec.push(Value::default()),
224                    }
225                    Value::Array(vec)
226                }
227                None => {
228                    let mut map = Map::default();
229                    map.insert(field.to_string(), Value::default());
230                    Value::Object(map)
231                }
232            };
233
234            match (json_value.clone(), new_value.clone()) {
235                (Value::Array(vec), Value::Object(_)) => {
236                    json_value.merge(new_value);
237                    let size = vec.len().to_string();
238                    let mut new_fields: Vec<&str> = vec![&size, field];
239                    new_fields.append(&mut fields.clone());
240                    merge_in(json_value, new_fields, new_json_value);
241                }
242                (_, _) => {
243                    let mut new_fields: Vec<&str> = vec![field];
244                    new_fields.append(&mut fields.clone());
245                    json_value.merge(new_value);
246                    merge_in(json_value, new_fields, new_json_value);
247                }
248            }
249        }
250    };
251}
252
253#[cfg(test)]
254mod tests {
255    use super::*;
256    use serde_json::json;
257
258    #[test]
259    fn can_merge_two_valid_jsons() {
260        let mut a = json!({
261            "title": "This is a title",
262            "person" : {
263                "firstName" : "John",
264                "lastName" : "Doe"
265            },
266            "cities":[ "london", "paris" ]
267        });
268
269        let b = json!({
270            "title": "This is another title",
271            "person" : {
272                "firstName" : "Jane"
273            },
274            "cities":[ "colombo" ]
275        });
276        merge_json(&mut a, b);
277
278        assert_eq!(
279            a,
280            json!({
281                "title": "This is another title",
282                "person" : {
283                    "firstName" : "Jane",
284                    "lastName" : "Doe"
285                },
286                "cities":[ "london", "paris", "colombo" ]
287            })
288        );
289    }
290
291    #[test]
292    fn it_should_merge_array_string() {
293        let mut first_json_value: Value = serde_json::from_str(r#"["a","b"]"#).unwrap();
294        let secound_json_value: Value = serde_json::from_str(r#"["b","c"]"#).unwrap();
295        first_json_value.merge(secound_json_value);
296        assert_eq!(r#"["a","b","c"]"#, first_json_value.to_string());
297    }
298    #[test]
299    fn it_should_merge_array_object() {
300        let mut first_json_value: Value =
301            serde_json::from_str(r#"[{"value":"a"},{"value":"b"}]"#).unwrap();
302        let secound_json_value: Value =
303            serde_json::from_str(r#"[{"value":"b"},{"value":"c"}]"#).unwrap();
304        first_json_value.merge(secound_json_value);
305        assert_eq!(
306            r#"[{"value":"a"},{"value":"b"},{"value":"c"}]"#,
307            first_json_value.to_string()
308        );
309    }
310    #[test]
311    fn it_should_merge_object() {
312        let mut first_json_value: Value =
313            serde_json::from_str(r#"{"value1":"a","value2":"b"}"#).unwrap();
314        let secound_json_value: Value =
315            serde_json::from_str(r#"{"value1":"a","value2":"c","value3":"d"}"#).unwrap();
316        first_json_value.merge(secound_json_value);
317        assert_eq!(
318            r#"{"value1":"a","value2":"c","value3":"d"}"#,
319            first_json_value.to_string()
320        );
321    }
322    #[test]
323    fn it_should_merge_string() {
324        let mut value_a: Value = Value::String("a".to_string());
325        let value_b: Value = Value::String("b".to_string());
326        value_a.merge(value_b.clone());
327        assert_eq!(value_b.to_string(), value_a.to_string());
328    }
329    #[test]
330    fn it_should_merge_an_array_in_a_specifique_field_path() {
331        let mut value_a: Value = serde_json::from_str(r#"{"my_array":[{"a":"t"}]}"#).unwrap();
332        let value_b: Value = serde_json::from_str(r#"["b","c"]"#).unwrap();
333        value_a.merge_in("/my_array", value_b);
334        assert_eq!(r#"{"my_array":[{"a":"t"},"b","c"]}"#, value_a.to_string());
335    }
336    #[test]
337    fn it_should_merge_an_object_in_a_specifique_field_path() {
338        let mut value_a: Value = serde_json::from_str(r#"{"my_array":[{"a":"t"}]}"#).unwrap();
339        let value_b: Value = serde_json::from_str(r#"{"b":"c"}"#).unwrap();
340        value_a.merge_in("/my_array", value_b);
341        assert_eq!(r#"{"my_array":[{"a":"t"},{"b":"c"}]}"#, value_a.to_string());
342    }
343    #[test]
344    fn it_should_merge_in_an_object_in_specifique_path_position() {
345        let mut value_a: Value = serde_json::from_str(r#"{"my_array":[{"a":"t"}]}"#).unwrap();
346        let value_b: Value = serde_json::from_str(r#"{"b":"c"}"#).unwrap();
347        value_a.merge_in("/my_array/0", value_b);
348        assert_eq!(r#"{"my_array":[{"a":"t","b":"c"}]}"#, value_a.to_string());
349    }
350    #[test]
351    fn it_should_merge_an_array_in_specifique_path_position() {
352        let mut value_a: Value = serde_json::from_str(r#"{"my_array":[{"a":"t"}]}"#).unwrap();
353        let value_b: Value = serde_json::from_str(r#"{"b":"c"}"#).unwrap();
354        value_a.merge_in("/my_array/1", value_b);
355        assert_eq!(r#"{"my_array":[{"a":"t"},{"b":"c"}]}"#, value_a.to_string());
356    }
357    #[test]
358    fn it_should_merge_in_root_array() {
359        let mut json_value: Value = serde_json::from_str(r#"["value"]"#).unwrap();
360        let json_value_to_merge: Value = serde_json::from_str(r#"["new_value"]"#).unwrap();
361        json_value.merge_in("/", json_value_to_merge);
362        assert_eq!(r#"["value","new_value"]"#, json_value.to_string());
363    }
364    #[test]
365    fn it_should_merge_in_root_object() {
366        let mut json_value: Value = serde_json::from_str(r#"{"field":"value"}"#).unwrap();
367        let json_value_to_merge: Value = serde_json::from_str(r#"{"field2":"value2"}"#).unwrap();
368        json_value.merge_in("/", json_value_to_merge);
369        assert_eq!(
370            r#"{"field":"value","field2":"value2"}"#,
371            json_value.to_string()
372        );
373    }
374    #[test]
375    fn it_should_merge_null_in_specifique_path() {
376        let mut json_value: Value = serde_json::from_str(r#"{"field":{"child":"value"}}"#).unwrap();
377        let json_value_null: Value = Value::Null;
378        json_value.merge_in("/field", json_value_null);
379        assert_eq!(r#"{"field":null}"#, json_value.to_string());
380    }
381}