Struct::Diff - Recursive diff for nested perl structures
Version 0.96
use Struct::Diff qw(diff list_diff split_diff patch valid_diff); $x = {one => [1,{two => 2}]}; $y = {one => [1,{two => 9}],three => 3}; $diff = diff($x, $y, noO => 1, noU => 1); # omit unchanged items and old values # $diff == {D => {one => {D => [{D => {two => {N => 9}},I => 1}]},three => {A => 3}}} @list_diff = list_diff($diff); # list (path and ref pairs) all diff entries # @list_diff == ({K => ['one']},[1],{K => ['two']}],\{N => 9},[{K => ['three']}],\{A => 3}) $splitted = split_diff($diff); # $splitted->{a} # does not exist # $splitted->{b} == {one => [{two => 9}],three => 3} patch($x, $diff); # $x now equal to $y by structure and data @errors = valid_diff($diff);
Nothing is exported by default.
Diff is simply a HASH whose keys shows status for each item in passed structures. Every status type (except D) may be omitted during the diff calculation. Disabling some or other types produce different diffs: diff with only unchanged items is also possible (when all other types disabled).
D
Stands for 'added' (exists only in second structure), it's value - added item.
Means 'different' and contains subdiff. The only status type which can't be disabled.
Index for array item, used only when prior item was omitted.
Is a new value for changed item.
Alike N, O is a changed item's old value.
N
O
Similar for A, but for removed items.
A
Represent unchanged items.
Diff format: metadata alternates with data and, as a result, diff may represent any structure of any data types. Simple types specified as is, arrays and hashes contain subdiffs for their items with native for such types addressing: indexes for arrays and keys for hashes.
Sample:
old: {one => [5,7]} new: {one => [5],two => 2} opts: {noU => 1} # omit unchanged items diff: {D => {one => {D => [{I => 1,R => 7}]},two => {A => 2}}} || | | || ||| | | | | || | || | | || ||| | | | | || +- with value 2 || | | || ||| | | | | |+- it says key was added || | | || ||| | | | | +- subdiff for it || | | || ||| | | | +- another key from top-level hash || | | || ||| | | +- what it was (item's value: 7) || | | || ||| | +- shows what happened to item (removed) || | | || ||| +- array item's actual index || | | || ||+- prior item was omitted || | | || |+- subdiff for array item || | | || +- it's value - ARRAY || | | |+- it is deeply changed || | | +- subdiff for key 'one' || | +- it has key 'one' || +- top-level thing is a HASH |+- changes somewhere deeply inside +- diff is always a HASH
Returns hashref to recursive diff between two passed things. Beware when changing diff: it's parts are links to original structures.
$diff = diff($x, $y, %opts); $patch = diff($x, $y, noU => 1, noO => 1, trimR => 1); # smallest possible diff
<sub>
Serializer callback (redefines default serializer). "freeze" in Storable is used by default, see "CONFIGURATION VARIABLES" for details.
<true|false>
Where X is a status (A, N, O, R, U); such status will be omitted.
R
U
Drop removed item's data.
List all pairs (path_to_subdiff, ref_to_subdiff) for provided diff. See "ADDRESSING SCHEME" in Struct::Path for path format specification.
@list = list_diff($diff);
<int>
Don't dive deeper than defined number of levels; undef used by default (unlimited).
undef
<sub|true|false>
Defines how to handle hash subdiffs. Keys will be picked randomely (default keys behavior), sorted by provided subroutine (if value is a coderef) or lexically sorted if set to some other true value.
keys
Divide diff to pseudo original structures.
$structs = split_diff(diff($x, $y)); # $structs->{a}: items from $x # $structs->{b}: items from $y
Apply diff.
patch($target, $diff);
Validate diff structure. In scalar context returns 1 for valid diff, undef otherwise. In list context returns list of pairs (path, type) for each error. See "ADDRESSING SCHEME" in Struct::Path for path format specification.
1
@errors_list = valid_diff($diff); # list context
or
$is_valid = valid_diff($diff); # scalar context
Contains reference to default serialization function (diff() rely on it to determine data equivalency). "freeze" in Storable with enabled $Storable::canonical and $Storable::Deparse opts used by default.
diff()
$Storable::canonical
$Storable::Deparse
Data::Dumper is suitable for structures with regular expressions:
use Data::Dumper; $Struct::Diff::FREEZER = sub { local $Data::Dumper::Deparse = 1; local $Data::Dumper::Sortkeys = 1; local $Data::Dumper::Terse = 1; return Dumper @_; }
But comparing to Storable it has two other issues: speed and unability to distinguish numbers from their string representations.
Only arrays and hashes traversed. All other types compared by reference address and serialized content.
"freeze" in Storable (serializer used by default) will fail serializing compiled regexps, so, consider to use other serializer if data contains regular expressions. See "CONFIGURATION VARIABLES" for details.
Struct::Diff will fail on structures with loops in references; has_circular_ref from Data::Structure::Util can help to detect such structures.
has_circular_ref
Michael Samoglyadov, <mixas at cpan.org>
<mixas at cpan.org>
Please report any bugs or feature requests to bug-struct-diff at rt.cpan.org, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Struct-Diff. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
bug-struct-diff at rt.cpan.org
You can find documentation for this module with the perldoc command.
perldoc Struct::Diff
You can also look for information at:
RT: CPAN's request tracker (report bugs here)
http://rt.cpan.org/NoAuth/Bugs.html?Dist=Struct-Diff
AnnoCPAN: Annotated CPAN documentation
http://annocpan.org/dist/Struct-Diff
CPAN Ratings
http://cpanratings.perl.org/d/Struct-Diff
Search CPAN
http://search.cpan.org/dist/Struct-Diff/
Algorithm::Diff, Data::Deep, Data::Diff, Data::Difference, JSON::MergePatch
Data::Structure::Util, Struct::Path, Struct::Path::PerlStyle
Copyright 2015-2018 Michael Samoglyadov.
This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License.
See http://dev.perl.org/licenses/ for more information.
To install Struct::Diff, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Struct::Diff
CPAN shell
perl -MCPAN -e shell install Struct::Diff
For more information on module installation, please visit the detailed CPAN module installation guide.