///|
/// RFC 7386 JSON Merge Patch: recursively merge `patch` into `target`
/// and return the result. Object members set to `null` in the patch are
/// removed; objects merge recursively; any other patch value replaces
/// the target wholesale. Neither input is modified.
pub fn merge_patch(target : Json, patch : Json) -> Json {
match patch {
Object(patch_members) => {
let base : Map[String, Json] = match target {
Object(target_members) => {
let out : Map[String, Json] = Map([])
for k, v in target_members {
out.set(k, v)
}
out
}
_ => Map([])
}
for k, v in patch_members {
if v is Null {
let _ = base.remove(k)
} else {
let child = match base.get(k) {
Some(existing) => existing
None => Json::null()
}
base.set(k, merge_patch(child, v))
}
}
Json::object(base)
}
_ => patch
}
}
///|
/// Text-level convenience for `merge_patch`.
pub fn merge(
target_text : String,
patch_text : String,
) -> Result[String, TextJsonError] {
let target : Json = @json.parse(target_text) catch {
e => return Err(BadTargetJson(e.to_string()))
}
let patch : Json = @json.parse(patch_text) catch {
e => return Err(BadPatchJson(e.to_string()))
}
Ok(merge_patch(target, patch).stringify())
}