I am trying to compare 2 different pieces of (Javascript/JSON) code using difflib
module in Python 3.8,
{"message": "Hello world", "name": "Jack"}
and
{"message": "Hello world", "name": "Ryan"}
Problem: When these 2 strings are prettified and compared using difflib
, we get the inline differences, as well as all the common lines.
Is there a way to only show the lines that differ, in a manner thats clearer to look at? This will help significantly when both files are much larger in size, making it more challenging to identify the changed lines.
Thanks!
Actual Output
{
"message": "Hello world",
"name": "{J -> Ry}a{ck -> n}"
}
Desired Output
"name": "{J -> Ry}a{ck -> n}"
Even better will be something like:
{"name": "Jack"} -> {"name": "Ryan"}
Python Code Used
We use jsbeautifier
here instead of json
because the files we are comparing may sometimes be malformed JSON. json
will throw an error while jsbeautifier
still formats it the way we expect it to.
import jsbeautifier
def inline_diff(a, b):
"""
https://stackoverflow.com/questions/774316/python-difflib-highlighting-differences-inline/47617607#47617607
"""
import difflib
matcher = difflib.SequenceMatcher(None, a, b)
def process_tag(tag, i1, i2, j1, j2):
if tag == 'replace':
return '{' + matcher.a[i1:i2] + ' -> ' + matcher.b[j1:j2] + '}'
if tag == 'delete':
return '{- ' + matcher.a[i1:i2] + '}'
if tag == 'equal':
return matcher.a[i1:i2]
if tag == 'insert':
return '{+ ' + matcher.b[j1:j2] + '}'
assert false, "Unknown tag %r"%tag
return ''.join(process_tag(*t) for t in matcher.get_opcodes())
# File content to compare
file1 = '{"message": "Hello world", "name": "Jack"}'
file2 = '{"message": "Hello world", "name": "Ryan"}'
# Prettify JSON
f1 = jsbeautifier.beautify(file1)
f2 = jsbeautifier.beautify(file2)
# Print the differences to stdout
print(inline_diff(f1, f2))