42 lines
1.5 KiB
Swift
42 lines
1.5 KiB
Swift
import Foundation
|
|
|
|
extension JSON {
|
|
|
|
/// Return a new JSON value by merging two other ones
|
|
///
|
|
/// If we call the current JSON value `old` and the incoming JSON value
|
|
/// `new`, the precise merging rules are:
|
|
///
|
|
/// 1. If `old` or `new` are anything but an object, return `new`.
|
|
/// 2. If both `old` and `new` are objects, create a merged object like this:
|
|
/// 1. Add keys from `old` not present in `new` (“no change” case).
|
|
/// 2. Add keys from `new` not present in `old` (“create” case).
|
|
/// 3. For keys present in both `old` and `new`, apply merge recursively to their values (“update” case).
|
|
public func merging(with new: JSON) -> JSON {
|
|
|
|
// If old or new are anything but an object, return new.
|
|
guard case .object(let lhs) = self, case .object(let rhs) = new else {
|
|
return new
|
|
}
|
|
|
|
var merged: [String: JSON] = [:]
|
|
|
|
// Add keys from old not present in new (“no change” case).
|
|
for (key, val) in lhs where rhs[key] == nil {
|
|
merged[key] = val
|
|
}
|
|
|
|
// Add keys from new not present in old (“create” case).
|
|
for (key, val) in rhs where lhs[key] == nil {
|
|
merged[key] = val
|
|
}
|
|
|
|
// For keys present in both old and new, apply merge recursively to their values.
|
|
for key in lhs.keys where rhs[key] != nil {
|
|
merged[key] = lhs[key]?.merging(with: rhs[key]!)
|
|
}
|
|
|
|
return JSON.object(merged)
|
|
}
|
|
}
|