Search code examples
jsonrustserdejson-patchserde-json

How can I merge two JSON objects with Rust?


I have two JSON files:

JSON 1

{
  "title": "This is a title",
  "person" : {
    "firstName" : "John",
    "lastName" : "Doe"
  },
  "cities":[ "london", "paris" ]
}

JSON 2

{
  "title": "This is another title",
  "person" : {
    "firstName" : "Jane"
  },
  "cities":[ "colombo" ]
}

I want to merge #2 into #1 where #2 overrides #1, producing following output:

{
  "title": "This is another title",
  "person" : {
    "firstName" : "Jane",
    "lastName" : "Doe"
  },
  "cities":[ "colombo" ]
}

I checked out the crate json-patch which does this but it does not compile against stable Rust. Is it possible to do something similar with something like serde_json and stable Rust?


Solution

  • Placing the answer suggested by Shepmaster below

    #[macro_use]
    extern crate serde_json;
    
    use serde_json::Value;
    
    fn merge(a: &mut Value, b: Value) {
        match (a, b) {
            (a @ &mut Value::Object(_), Value::Object(b)) => {
                let a = a.as_object_mut().unwrap();
                for (k, v) in b {
                    merge(a.entry(k).or_insert(Value::Null), v);
                }
            }
            (a, b) => *a = b,
        }
    }
    
    fn main() {
        let mut a = json!({
            "title": "This is a title",
            "person" : {
                "firstName" : "John",
                "lastName" : "Doe"
            },
            "cities":[ "london", "paris" ]
        });
    
        let b = json!({
            "title": "This is another title",
            "person" : {
                "firstName" : "Jane"
            },
            "cities":[ "colombo" ]
        });
    
        merge(&mut a, b);
        println!("{:#}", a);
    }