File Coverage

lib/Convert/Pheno/IO.pm
Criterion Covered Total %
statement 63 68 92.6
branch 7 8 87.5
condition n/a
subroutine 18 19 94.7
pod 0 6 0.0
total 88 101 87.1


line stmt bran cond sub pod time code
1             package Convert::Pheno::IO;
2              
3 6     6   48 use strict;
  6         9  
  6         189  
4 6     6   27 use warnings;
  6         10  
  6         141  
5 6     6   31 use autodie;
  6         10  
  6         38  
6 6     6   33571 use feature qw(say);
  6         11  
  6         530  
7 6     6   48 use Path::Tiny;
  6         11  
  6         402  
8 6     6   41 use File::Basename;
  6         11  
  6         446  
9 6     6   37 use List::Util qw(any);
  6         44  
  6         403  
10 6     6   2879 use YAML::XS qw(LoadFile DumpFile);
  6         17863  
  6         409  
11             $YAML::XS::Boolean = 'JSON::PP'; # use JSON::PP::Boolean objects
12 6     6   54 use JSON::XS;
  6         31  
  6         348  
13 6     6   40 use Sort::Naturally qw(nsort);
  6         12  
  6         266  
14 6     6   3170 use Data::Leaf::Walker;
  6         9382  
  6         199  
15 6     6   54 use Exporter 'import';
  6         8  
  6         3876  
16             our @EXPORT = qw(read_json read_yaml io_yaml_or_json write_json write_yaml);
17              
18             #########################
19             #########################
20             # SUBROUTINES FOR I/O #
21             #########################
22             #########################
23              
24             sub read_json {
25              
26 10     10 0 84 my $str = path(shift)->slurp_utf8;
27 10         12548 return decode_json($str); # Decode to Perl data structure
28             }
29              
30             sub read_yaml {
31              
32 12     12 0 82 my $data = LoadFile(shift); # Decode to Perl data structure
33 7         6692 traverse_yaml_data_to_coerce_numbers($data)
34             ; # revert floatings getting stringified by YAML::XS
35 7         567 return $data;
36             }
37              
38             sub io_yaml_or_json {
39              
40 32     32 0 80 my $arg = shift;
41 32         78 my $file = $arg->{filepath};
42 32         57 my $mode = $arg->{mode};
43 32 100       129 my $data = $mode eq 'write' ? $arg->{data} : undef;
44              
45             # Checking only for qw(.yaml .yml .json)
46 32         113 my @exts = qw(.yaml .yml .json);
47 32         170 my $msg = qq(Can't recognize <$file> extension. Extensions allowed are: )
48             . join ',', @exts;
49 32         2124 my ( undef, undef, $ext ) = fileparse( $file, @exts );
50 32 100   72   410 die $msg unless any { $_ eq $ext } @exts;
  72         3519  
51              
52             # To simplify return values, we create a hash
53 30         139 $ext =~ tr/a.//d; # Unify $ext (delete 'a' and '.')
54 30         331 my $return = {
55             read => { json => \&read_json, yml => \&read_yaml },
56             write => { json => \&write_json, yml => \&write_yaml }
57             };
58              
59             # We return according to the mode (read or write) and format
60             return $mode eq 'read'
61             ? $return->{$mode}{$ext}->($file)
62 30 100       215 : $return->{$mode}{$ext}->( { filepath => $file, data => $data } );
63             }
64              
65             sub write_json {
66              
67 8     8 0 19 my $arg = shift;
68 8         21 my $file = $arg->{filepath};
69 8         18 my $json_data = $arg->{data};
70 8         31146 my $json = JSON::XS->new->utf8->canonical->pretty->encode($json_data);
71 8         132 path($file)->spew_utf8($json);
72 8         18925 return 1;
73             }
74              
75             sub write_yaml {
76              
77 0     0 0 0 my $arg = shift;
78 0         0 my $file = $arg->{filepath};
79 0         0 my $json_data = $arg->{data};
80 0         0 DumpFile( $file, $json_data );
81 0         0 return 1;
82             }
83              
84             sub traverse_yaml_data_to_coerce_numbers {
85              
86 7     7 0 27 my $data = shift;
87              
88             # Traversing the data to force numbers to be numbers
89             # NB: Changing the original data structure
90 7         106 my $walker = Data::Leaf::Walker->new($data);
91 7         330 while ( my ( $key_path, $value ) = $walker->each ) {
92 1218 50       50291 $walker->store( $key_path, $value + 0 )
93             if Scalar::Util::looks_like_number $value;
94             }
95             }
96             1;