initial commit
This commit is contained in:
commit
d0f1b8287d
|
@ -0,0 +1,12 @@
|
|||
Copyright (c) 2019 Christine Dodrill <me@christine.website>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
|
@ -0,0 +1,14 @@
|
|||
# Package
|
||||
|
||||
version = "0.1.0"
|
||||
author = "Christine Dodrill"
|
||||
description = "Store JSON objects and patches to them, then query the aggregate object"
|
||||
license = "0BSD"
|
||||
srcDir = "src"
|
||||
bin = @["objpatch"]
|
||||
|
||||
|
||||
|
||||
# Dependencies
|
||||
|
||||
requires "nim >= 0.20.2"
|
|
@ -0,0 +1,56 @@
|
|||
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}"
|
Loading…
Reference in New Issue