AutoCat2/Shared/ThirdParty/GenericJSON/Merging.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)
}
}