Skip to content

Instantly share code, notes, and snippets.

@jroelofs
Last active August 29, 2015 14:22
Show Gist options
  • Save jroelofs/8d410621a6ea168c75fe to your computer and use it in GitHub Desktop.
Save jroelofs/8d410621a6ea168c75fe to your computer and use it in GitHub Desktop.
Diff program for JSON dictionaries

JSON Differ

Usage

$ jdiff.py from-file to-file
#!/usr/bin/env python
import sys
import json
def string_from_keypath(keypath):
return 'dict["' + ('"]["'.join(keypath)) + '"]'
class ValueChange(object):
def __init__(self, keypath, lhs, rhs):
self.keypath = keypath
self.lhs = lhs
self.rhs = rhs
def dump(self):
print "@@ ", string_from_keypath(self.keypath), " @@"
print "- ", self.lhs
print "+ ", self.rhs
class KeyAddition(object):
def __init__(self, keypath, value):
self.keypath = keypath
self.value = value
def dump(self):
print "@@ ", string_from_keypath(self.keypath), " @@"
print "+ ", self.value
class KeyDeletion(object):
def __init__(self, keypath, value):
self.keypath = keypath
self.value = value
def dump(self):
print "@@ ", string_from_keypath(self.keypath), " @@"
print "- ", self.value
def recursive_diff(keypath, lhs, rhs):
if type(lhs) != type(rhs):
return [ValueChange(keypath, lhs, rhs)]
if type(rhs) != dict:
if lhs != rhs:
return [ValueChange(keypath, lhs, rhs)]
else:
return []
changes = []
for key in lhs.keys():
if key not in rhs.keys():
changes += [KeyDeletion(keypath + [key], lhs[key])]
for key in rhs.keys():
if key not in lhs.keys():
changes += [KeyAddition(keypath + [key], rhs[key])]
for key in lhs.keys():
if key in rhs.keys():
changes += recursive_diff(keypath + [key], lhs[key], rhs[key])
return changes
def main():
lhs_filename = sys.argv[1]
with open(lhs_filename, "r") as lhs_file:
lhs_text = lhs_file.read()
lhs = json.loads(lhs_text)
rhs_filename = sys.argv[2]
with open(rhs_filename, "r") as rhs_file:
rhs_text = rhs_file.read()
rhs = json.loads(rhs_text)
changes = recursive_diff([], lhs, rhs)
if len(changes) == 0:
sys.exit(0)
print "--- ", sys.argv[1]
print "+++ ", sys.argv[2]
for change in changes:
change.dump()
sys.exit(-1)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment