Shows difference between two json like python objects. May help to test json response, piston API powered sites... Shows properties, values from first object that are not in the second.
Example:
import simplejson # or other json serializer
first = simplejson.loads('{"first_name": "Poligraph", "last_name": "Sharikov",}')
second = simplejson.loads('{"first_name": "Poligraphovich", "pet_name": "Sharik"}')
df = Diff(first, second)
df.difference is ["path: last_name"]
Diff(first, second, vice_versa=True) gives you difference from both objects in the one result.
df.difference is ["path: last_name", "path: pet_name"]
Diff(first, second, with_values=True) gives you difference of the values strings.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | class Diff(object):
def __init__(self, first, second, with_values=False, vice_versa=False):
self.difference = []
self.check(first, second, with_values=with_values)
if vice_versa:
self.check(second, first, with_values=with_values)
def check(self, first, second, path='', with_values=False):
if second != None:
if not isinstance(first, type(second)):
message = '%s- %s, %s' % (path, type(first), type(second))
self.save_diff(message, TYPE)
if isinstance(first, dict):
for key in first:
# the first part of path must not have trailing dot.
if len(path) == 0:
new_path = key
else:
new_path = "%s.%s" % (path, key)
if isinstance(second, dict):
if second.has_key(key):
sec = second[key]
else:
# there are key in the first, that is not presented in the second
self.save_diff(new_path, PATH)
# prevent further values checking.
sec = None
# recursive call
self.check(first[key], sec, path=new_path, with_values=with_values)
else:
# second is not dict. every key from first goes to the difference
self.save_diff(new_path, PATH)
self.check(first[key], second, path=new_path, with_values=with_values)
# if object is list, loop over it and check.
elif isinstance(first, list):
for (index, item) in enumerate(first):
new_path = "%s[%s]" % (path, index)
# try to get the same index from second
sec = None
if second != None:
try:
sec = second[index]
except (IndexError, KeyError):
# goes to difference
self.save_diff('%s - %s, %s' % (new_path, type(first), type(second)), TYPE)
# recursive call
self.check(first[index], sec, path=new_path, with_values=with_values)
# not list, not dict. check for equality (only if with_values is True) and return.
else:
if with_values and second != None:
if first != second:
self.save_diff('%s - %s | %s' % (path, first, second), VALUE)
return
def save_diff(self, diff_message, type_):
message = '%s: %s' % (type_, diff_message)
if diff_message not in self.difference:
self.difference.append(message)
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 11 months, 2 weeks ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 11 months, 3 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 6 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 7 months ago
- Help text hyperlinks by sa2812 1 year, 7 months ago
Comments
For dicts, you might try to use
set(dict1.iteritems()) - set(dict2.iteritems())
which will compute the difference for you. fast and efficient. For lists, you might useset(enumerate(list1)) - set(enumerate(list2))
. Now generalize the mapper and useset(mapper(json1)) - set(mapper(json2))
. No need for 66 lines, which are completely unrelated to Django.#
I think it's good, but not for all cases.
`fir = {"f": "foo"}
sec = {"f": "bar"}`
Your method gives us '[('f', 'foo')]' difference, but the both has the same keys.
`fir = {"f": "foo"}
sec = {"f": [1]}`
Your method does not give you proper difference.
`fir = {"f": {"f": "fir"}}
sec = {"f": {"b": "bar"}}`
#
Please login first before commenting.