File Coverage

blib/lib/Data/Ref/JSON.pm
Criterion Covered Total %
statement 46 112 41.0
branch 2 32 6.2
condition 2 6 33.3
subroutine 13 18 72.2
pod 0 4 0.0
total 63 172 36.6


line stmt bran cond sub pod time code
1              
2             package Data::Ref::JSON;
3 1     1   66844 use strict;
  1         2  
  1         28  
4 1     1   6 use Carp;
  1         2  
  1         49  
5 1     1   5 use warnings;
  1         2  
  1         34  
6 1     1   2233 use diagnostics;
  1         222644  
  1         12  
7 1     1   1135 use Data::Dumper;
  1         7000  
  1         78  
8 1     1   558 use Try::Tiny;
  1         2168  
  1         68  
9              
10             # 0 is 'disabled'
11             my $debugLevel=0;
12              
13             BEGIN {
14 1     1   7 use Exporter ();
  1         3  
  1         29  
15 1     1   12 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
  1         2  
  1         124  
16 1     1   4 $VERSION = '0.02';
17 1         17 @ISA = qw(Exporter);
18 1         3 @EXPORT = qw();
19 1         18 @EXPORT_OK = qw(&pdebug &setDebugLevel &walk);
20 1         1314 %EXPORT_TAGS = ();
21             }
22              
23             my %walkType = (
24             'HASH' => \&_walkHash,
25             'ARRAY' => \&_walkArray,
26             );
27              
28             sub _setDebugLevel {
29 1     1   5 ($debugLevel) = @_;
30 1         3 return;
31             }
32              
33             sub _getDebugLevel {
34 2     2   15 return $debugLevel;
35             }
36              
37             =head1 setDebugLevel
38              
39             For procedural use.
40              
41             Call as setDebugLevel($i);
42              
43             A value of 0 disables debugging output (default)
44              
45             =cut
46              
47             sub setDebugLevel {
48 0     0 0 0 _setDebugLevel $_[0];
49 0         0 return;
50             }
51              
52             sub _walkArray {
53 0     0   0 my ( $ar, $refStr) = @_;
54 0         0 my ($package, $filename, $line, $subroutine) = caller(0);
55 0         0 pdebug(1,"subroutine: " . $subroutine,"\n" );
56 0         0 pdebug(1, "$subroutine: top dump array:\n" , Dumper($ar), "\n");
57 0         0 foreach my $idx ( 0 .. $#${ar} ) {
58 0         0 my $refType = ref $ar->[$idx];
59 0 0       0 $refType = ref \$ar->[$idx] unless $refType;
60 0         0 pdebug(1, "$subroutine: refType - $refType\n");
61 0 0       0 if ( $refType eq 'SCALAR') {
    0          
    0          
62 0         0 print "i:v, $idx:$ar->[$idx]\n";
63             #print "refStr: $refStr" . q(->[). $idx . q(]) . "\n";
64 0         0 print "refStr: $refStr" . q([). $idx . q(]) . "\n";
65             } elsif ($refType eq 'ARRAY') {
66 0         0 pdebug(1, "$subroutine nested array: ", Dumper($ar->[$idx]),"\n");
67 0         0 pdebug(1, "$subroutine calling walk with 'ARRAY'\n","\n");
68 0         0 _walk($ar->[$idx], $idx, $refStr . q([). $idx . q(]));
69             } elsif ($refType eq 'HASH') {
70 0         0 pdebug(1, "$subroutine calling walk with 'HASH'\n","\n");
71 0         0 _walk($ar->[$idx], $idx, $refStr . q([). $idx . q(]));
72             } else {
73 0         0 croak "something broke in $subroutine\n";
74             }
75             }
76             }
77              
78             sub _walkHash {
79 0     0   0 my ( $hr, $refStr) = @_;
80              
81 0         0 my ($package, $filename, $line, $subroutine) = caller(0);
82 0         0 pdebug(1,"subroutine: " . $subroutine,"\n" );
83 0         0 pdebug(1, "$subroutine: top dump hash\n" , Dumper($hr), "\n");
84             # using sort just to see results in the same order consistently when testing
85             # could make use of 'sort' an option
86 0         0 foreach my $key ( sort keys %{$hr}) {
  0         0  
87 0         0 pdebug(1,"key: $key\n");
88 0         0 my $keyRefType = ref $hr->{$key};
89 0 0       0 if ( $keyRefType eq '' ) { $keyRefType = ref \$key }
  0         0  
90 0         0 pdebug(1, "$subroutine: keyRefType - $keyRefType\n");
91              
92 0         0 pdebug(1,"key refType: $keyRefType\n");
93 0 0       0 if ( $keyRefType eq 'SCALAR' ) {
    0          
    0          
94             #print "k:v, '$key':'" . defined($hr->{$key}) ? $hr->{$key} : 'NULL' . "'\n";
95 0 0       0 my $value = defined($hr->{$key}) ? $hr->{$key} : 'NULL';
96 0         0 print "k:v, '$key':'$value'\n";
97 0         0 print "refStr: $refStr" . q({'). $key . q('}) . "\n";
98             } elsif ($keyRefType eq 'ARRAY') {
99 0         0 pdebug(1, "$subroutine nested array: ", Dumper($hr->{$key}),"\n");
100 0         0 pdebug(1, "$subroutine calling walk with 'ARRAY'\n","\n");
101 0         0 _walk($hr->{$key}, $key, $refStr . q({'). $key . q('}));
102             } elsif ($keyRefType eq 'HASH') {
103 0         0 pdebug(1, "$subroutine nested hash ", Dumper($hr->{$key}),"\n");
104 0         0 pdebug(1, "$subroutine calling walk with 'HASH'\n","\n");
105 0         0 _walk($hr->{$key}, $key, $refStr . q({'). $key . q('}));
106             } else {
107 0         0 croak "something broke in $subroutine\n";
108             }
109             }
110              
111             }
112              
113             # key could be a hash key or an array index
114              
115             sub _walk {
116            
117 0     0   0 my ($structRef, $key, $refStr) = @_;
118              
119 0         0 my ($package, $filename, $line, $subroutine) = caller(0);
120              
121 0         0 pdebug(1,"subroutine: " . $subroutine );
122              
123 0         0 my $refType = ref $structRef;
124 0         0 pdebug(1,"$subroutine refType: $refType\n");
125              
126 0 0       0 if ( ! defined $refStr ) {$refStr = 'VAR->'}
  0         0  
127              
128 0         0 pdebug(1,"$subroutine: ", Dumper ($structRef));
129              
130             # I believe this block is never executed
131 0 0       0 if ( $refType eq '' ) { # check for scalar
132             #no strict 'refs';
133 0         0 my $t = $structRef;
134 0         0 pdebug(2,'t: refType - ' , ref \$t, "\n");
135 0         0 pdebug(2,'t: ', Dumper($t));
136 0         0 warn "BLOCK HAS EXECUTED\n";
137             }
138              
139 0 0       0 if ( $refType eq 'REF' ) {
    0          
140 0         0 carp "Do not know how to handle type of 'REF'.\n";
141 0         0 carp "Perhaps you have unncessarily referenced a variable with \?\n";
142 0         0 croak "unsupported reference\n";
143             } elsif ($refType eq '' ) { # check for scalar - leaf node
144 0         0 croak "Something went wrong - refType is '$refType'\n";
145             } else {
146 0         0 $walkType{$refType}($structRef,$refStr);
147             }
148             }
149              
150             =head1 walk
151              
152             Walk the data structure and print the string required to access it
153              
154             This can be used as an object or a procedure
155              
156             =cut
157              
158             =head2 As Procedure
159              
160             use Data::Ref::JSON qw(walk);
161              
162             my %tc = (
163              
164             'HL01-01' => {
165             'HL02-01' => [
166             'element 0',
167             'element 1',
168             'element 2'
169             ]
170             },
171              
172             'HL01-02' => {
173             'HL02-01' => {
174             K4 => 'this is key 4',
175             K5 => 'this is key 5',
176             K6 => 'this is key 6'
177             }
178             }
179              
180             );
181              
182             walk(\%tc);
183              
184              
185             =cut
186              
187             =head2 As Object
188              
189             use Data::Ref::JSON;
190              
191             my %tc = (
192              
193             'HL01-01' => {
194             'HL02-01' => [
195             'element 0',
196             'element 1',
197             'element 2'
198             ]
199             },
200              
201             'HL01-02' => {
202             'HL02-01' => {
203             K4 => 'this is key 4',
204             K5 => 'this is key 5',
205             K6 => 'this is key 6'
206             }
207             }
208              
209             );
210              
211             my $dr = Data::Ref::JSON->new (
212             {
213             DEBUG => 0,
214             DATA => \%tc
215             }
216             );
217              
218             $dr->walk;
219              
220              
221             =cut
222              
223             sub walk {
224              
225 0 0   0 0 0 if ( ref($_[0]) eq 'Data::Ref::JSON' ) {
226 0         0 my $self = shift;
227 0         0 _walk($self->{DATA});
228             } else {
229 0         0 my $data = shift;
230 0         0 _walk($data);
231             }
232              
233             }
234              
235             sub pdebug {
236 2     2 0 157 my $dlvl = shift;
237 2 50 33     5 print "\ndbg:", join("\ndbg: ",@_) if _getDebugLevel() and $dlvl <= _getDebugLevel();
238             }
239              
240             =head1 new
241              
242             Given an arbitrary data structure, create a new object that can then be traversed by walk().
243              
244             walk() will print all values and the string used to access them
245              
246             Given the following structure:
247              
248             (
249              
250             'HL01-01' => {
251             'HL02-01' => [
252             'element 0',
253             'element 1',
254             'element 2'
255             ]
256             },
257              
258             'HL01-02' => {
259             'HL02-01' => {
260             K4 => 'this is key 4',
261             K5 => 'this is key 5',
262             K6 => 'this is key 6'
263             }
264             }
265              
266             );
267              
268              
269             This would be the output:
270              
271             i:v, 0:element 0
272             refStr: VAR->{'HL01-01'}{'HL02-01'}[0]
273             i:v, 1:element 1
274             refStr: VAR->{'HL01-01'}{'HL02-01'}[1]
275             i:v, 2:element 2
276             refStr: VAR->{'HL01-01'}{'HL02-01'}[2]
277             k:v, 'K4':'this is key 4'
278             refStr: VAR->{'HL01-02'}{'HL02-01'}{'K4'}
279             k:v, 'K5':'this is key 5'
280             refStr: VAR->{'HL01-02'}{'HL02-01'}{'K5'}
281             k:v, 'K6':'this is key 6'
282             refStr: VAR->{'HL01-02'}{'HL02-01'}{'K6'}
283              
284             Where
285             i = position in array
286             k = hash key
287             v = value
288             refStr = the string used to access the value
289              
290             =cut
291              
292             #my %walkers = (
293             #'HASH' => 0,
294             #'ARRAY' => 1,
295             #);
296              
297             sub new
298             {
299              
300 1     1 0 90 my $pkg = shift;
301 1   33     9 my $class = ref($pkg) || $pkg;
302 1         2 my $parms= shift;
303 1         3 my $self = $parms;
304 1         3 my $retval = bless $self, $class;
305              
306 1         13 _setDebugLevel($parms->{DEBUG});
307              
308 1 50       15 croak "No Data Sent\n" unless $parms->{DATA};
309 1         5 $parms->{WORKING_DATA} = $parms->{DATA};
310              
311 1         10 my ($package, $filename, $line, $subroutine) = caller(0);
312              
313 1         11 pdebug(1,"$subroutine parms", Dumper($parms));
314              
315              
316 1         10 pdebug(1,"$subroutine - new self: ", Dumper($self));
317              
318             # may convert to this later
319             #$self->{walkers}[$walkType{'HASH'}] = sub { $self->_walkHash(); };
320             #$self->{walkers}[$walkType{'ARRAY'}] = sub { $self->_walkArray(); };
321              
322 1         13 return $retval;
323             }
324              
325              
326             =head1 NAME
327              
328             Data::Ref::JSON
329              
330             =head1 SYNOPSIS
331              
332            
333             Walk a referenced arbitrary data structure and provide the reference to access values
334            
335              
336             =head1 DESCRIPTION
337              
338              
339             When working with deeply nested complex data structures, it can be quite difficult to determine just what the key is for any value.
340              
341             Data::Ref::JSON will traverse the data, printing the values and the keys used to access them.
342            
343              
344             =head1 USAGE
345              
346             See the examples for walk()
347              
348              
349             =head1 BUGS
350              
351              
352              
353             =head1 SUPPORT
354              
355              
356              
357             =head1 AUTHOR
358              
359             Jared Still
360             CPAN ID: MODAUTHOR
361             Pythian
362             jkstill@gmail.com
363             http://a.galaxy.far.far.away/modules
364              
365             =head1 COPYRIGHT
366              
367             This program is free software licensed under the...
368              
369             The MIT License
370              
371             The full text of the license can be found in the
372             LICENSE file included with this module.
373              
374              
375             =head1 SEE ALSO
376              
377             perl(1).
378              
379             =cut
380              
381             #################### main pod documentation end ###################
382              
383              
384             1;
385             # The preceding line will help the module return a true value
386