57 lines
1.6 KiB
Nim
57 lines
1.6 KiB
Nim
import hashes, json, strformat, tables
|
|
|
|
proc diff(old, new: JsonNode): JsonNode =
|
|
## return the json fields that are different between the two objects
|
|
result = newJObject()
|
|
|
|
var
|
|
oldFields = old.getFields
|
|
newFields = new.getFields
|
|
oldHashes = newOrderedTable[string, Hash]()
|
|
newHashes = newOrderedTable[string, Hash]()
|
|
|
|
for k, v in old.getFields.pairs:
|
|
oldHashes[k] = v.hash
|
|
|
|
for k, v in new.getFields.pairs:
|
|
newHashes[k] = v.hash
|
|
|
|
if not old.contains(k):
|
|
result.add k, v
|
|
|
|
for k, v in oldHashes.pairs:
|
|
if newHashes.contains(k) and newHashes[k] != v:
|
|
if oldFields[k].kind == JObject:
|
|
result.add k, diff(oldFields[k], newFields[k])
|
|
else:
|
|
result.add k, newFields[k]
|
|
|
|
proc combine(old, patch: JsonNode): JsonNode =
|
|
## Applies the patch on top of the old data to get the resulting aggregate
|
|
## object.
|
|
result = newJObject()
|
|
var
|
|
oldFields = old.getFields
|
|
newFields = patch.getFields
|
|
|
|
for k, v in oldFields.pairs:
|
|
result.add k, v
|
|
|
|
for k, v in newFields.pairs:
|
|
if v.kind == JObject:
|
|
result.add k, combine(oldFields[k], newFields[k])
|
|
else:
|
|
result.add k, v
|
|
|
|
when isMainModule:
|
|
let
|
|
old = """{"foo": "bar", "shouldnt": "change", "obj": {"is": "fine", "too": false}}""".parseJson
|
|
new = """{"foo": "baz", "bar": "boz", "new": "data", "with_an_array": ["foo", "bar", "baz"], "obj": {"hi": "mom"}}""".parseJson
|
|
patch = old.diff new
|
|
res = old.combine patch
|
|
|
|
echo fmt"old: {old.pretty}"
|
|
echo fmt"new: {new.pretty}"
|
|
echo fmt"patch: {patch.pretty}"
|
|
echo fmt"result: {res.pretty}"
|