Package: nested-diff
Nested-Diff.pyRecursive diff and patch for nested structures.Main featuresMachine-readable diff structure.Human-friendly diff visualization, collapsible html diffs.All operation tags are optional and may be disabled.Extensibility.See Live Demo!Installpip install nested_diffFor extra formats support (YAML, TOML) in cli tools, usepip install nested_diff[cli]Command line tools$cata.jsonb.json[0,[1],3][0,[1,2],3]$nested_diffa.jsonb.json[1]+[1]+2nested_diffa.jsonb.json--ofmtjson>patch.json
nested_patcha.jsonpatch.jsonLibrary usage>>>fromnested_diffimportdiff,patch>>>>>>a={'one':1,'two':2,'three':3}>>>b={'one':1,'two':42}>>>>>>diff(a,b){'D':{'three':{'R':3},'two':{'N':42,'O':2},'one':{'U':1}}}>>>>>>diff(a,b,O=False,U=False){'D':{'three':{'R':3},'two':{'N':42}}}>>>>>>>>>c=[0,1,2,3]>>>d=[1,2,4,5]>>>>>>c=patch(c,diff(c,d))>>>assertc==d>>>Formatting diffs>>>fromnested_diffimportdiff,handlers>>>fromnested_diff.formattersimportTextFormatter>>>>>>a={'one':1,'two':'some\ntext\ninside'}>>>b={'one':0,'two':'some\ntext'}>>>>>>d=diff(a,b,U=False,extra_handlers=[handlers.TextHandler(context=3)])>>>print(TextFormatter().format(d)){'one'}-1+0{'two'}#   <str>@@-1,3+1,2@@sometext-inside<BLANKLINE>>>>For more examples seeLive Demo,HOWTOandtests.Diff structureDiff is a dict and may contain status keys:Astands for 'added', it's value - added item.Dmeans 'different' and contains subdiff.Nis a new value for changed item.Ois a changed item's old value.Rkey used for removed item.Urepresent unchanged item.and auxiliary keys:Ccomment; optional, value - arbitrary string.Eextension ID (optional).Iindex for sequence item, used only when prior item was omitted.Diff metadata alternates with actual data; simple types specified as is, dicts,
lists and tuples contain subdiffs for their items with native for such types
addressing: indexes for lists and tuples, keys for dictionaries. Any status
key, exceptDmay be omitted during diff computation.Ekey is used withDwhen entity unable to contain diff by itself (set, frozenset for example);Dcontain a list of subdiffs in this case.Annotated examplea:  {"one": [5,7]}
b:  {"one": [5], "two": 2}
opts: U=False  # omit unchanged items

diff:
{"D": {"one": {"D": [{"I": 1, "R": 7}]}, "two": {"A": 2}}}
| |   |  |    | |   || |   |   |   |       |    | |   |
| |   |  |    | |   || |   |   |   |       |    | |   +- with value 2
| |   |  |    | |   || |   |   |   |       |    | +- key 'two' was added
| |   |  |    | |   || |   |   |   |       |    +- subdiff for it
| |   |  |    | |   || |   |   |   |       +- another key from top-level
| |   |  |    | |   || |   |   |   +- what it was (item's value: 7)
| |   |  |    | |   || |   |   +- what happened to item (removed)
| |   |  |    | |   || |   +- list item's actual index
| |   |  |    | |   || +- prior item was omitted
| |   |  |    | |   |+- subdiff for list item
| |   |  |    | |   +- it's value - list
| |   |  |    | +- it is deeply changed
| |   |  |    +- subdiff for key 'one'
| |   |  +- it has key 'one'
| |   +- top-level thing is a dict
| +- changes somewhere deeply inside
+- diff is always a dictLicenseLicensed under the terms of theApache License, Version 2.0.See AlsoHOWTOdeepdiff,jsondiff,jsonpatch,json-delta