I liked @ user2215977's answer, but I also needed a merge of nested JSON. I expanded the extension to combine nested JSON and arrays, while arrays containing JSON are not merged, but both are in the array of the newly created JSON.
import SwiftyJSON
extension JSON { mutating func merge(other: JSON) { if self.type == other.type { switch self.type { case .dictionary: for (key, _) in other { self[key].merge(other: other[key]) } case .array: self = JSON(self.arrayValue + other.arrayValue) default: self = other } } else { self = other } } func merged(other: JSON) -> JSON { var merged = self merged.merge(other: other) return merged } }
To illustrate usage, I will also post my tests for this extension.
import XCTest import SwiftyJSON class JSONTests: XCTestCase { func testPrimitiveType() { let A = JSON("a") let B = JSON("b") XCTAssertEqual(A.merged(other: B), B) } func testMergeEqual() { let json = JSON(["a": "A"]) XCTAssertEqual(json.merged(other: json), json) } func testMergeUnequalValues() { let A = JSON(["a": "A"]) let B = JSON(["a": "B"]) XCTAssertEqual(A.merged(other: B), B) } func testMergeUnequalKeysAndValues() { let A = JSON(["a": "A"]) let B = JSON(["b": "B"]) XCTAssertEqual(A.merged(other: B), JSON(["a": "A", "b": "B"])) } func testMergeFilledAndEmpty() { let A = JSON(["a": "A"]) let B = JSON([:]) XCTAssertEqual(A.merged(other: B), A) } func testMergeEmptyAndFilled() { let A = JSON([:]) let B = JSON(["a": "A"]) XCTAssertEqual(A.merged(other: B), B) } func testMergeArray() { let A = JSON(["a"]) let B = JSON(["b"]) XCTAssertEqual(A.merged(other: B), JSON(["a", "b"])) } func testMergeNestedJSONs() { let A = JSON([ "nested": [ "A": "a" ] ]) let B = JSON([ "nested": [ "A": "b" ] ]) XCTAssertEqual(A.merged(other: B), B) } }
source share