File Coverage

blib/lib/DBIx/QuickORM/Type/JSON.pm
Criterion Covered Total %
statement 53 64 82.8
branch 8 20 40.0
condition 5 21 23.8
subroutine 15 16 93.7
pod 0 8 0.0
total 81 129 62.7


line stmt bran cond sub pod time code
1             package DBIx::QuickORM::Type::JSON;
2 3     3   26 use strict;
  3         8  
  3         218  
3 3     3   24 use warnings;
  3         7  
  3         298  
4              
5             our $VERSION = '0.000019';
6              
7 3     3   34 use DBIx::QuickORM::Util qw/parse_conflate_args/;
  3         9  
  3         27  
8              
9 3     3   196 use Carp qw/croak/;
  3         6  
  3         200  
10 3     3   22 use Scalar::Util qw/reftype blessed/;
  3         7  
  3         173  
11 3     3   21 use Role::Tiny::With qw/with/;
  3         6  
  3         224  
12             with 'DBIx::QuickORM::Role::Type';
13              
14 3     3   3833 use Cpanel::JSON::XS qw/decode_json/;
  3         26009  
  3         2807  
15              
16             my $JSON = Cpanel::JSON::XS->new->utf8(1)->convert_blessed(1)->allow_nonref(1);
17 9     9 0 148 sub JSON { $JSON }
18              
19             my $CJSON = Cpanel::JSON::XS->new->utf8(1)->convert_blessed(1)->allow_nonref(1)->canonical(1);
20 6     6 0 47 sub CJSON { $CJSON }
21              
22             sub qorm_inflate {
23 11     11 0 58 my $params = parse_conflate_args(@_);
24 11 50       48 my $val = $params->{value} or return undef;
25 11   50     41 my $class = $params->{class} // __PACKAGE__;
26              
27 11 100       43 return $val if ref($val);
28 7         912 return decode_json($val);
29             }
30              
31             sub qorm_deflate {
32 9     9 0 52 my $params = parse_conflate_args(@_);
33 9 50       44 my $val = $params->{value} or return undef;
34 9 50       35 my $affinity = $params->{affinity} or croak "Could not determine affinity";
35 9   50     67 my $class = $params->{class} // __PACKAGE__;
36              
37 9 50       61 if (blessed($val)) {
38 0   0     0 my $r = reftype($val) // '';
39 0 0       0 if ($r eq 'HASH') { $val = {%$val} }
  0 0       0  
40 0         0 elsif ($r eq 'ARRAY') { $val = [@$val] }
41 0         0 else { die "Not sure what to do with $val" }
42             }
43              
44 9         54 return $class->JSON->encode($val);
45             }
46              
47             sub qorm_compare {
48 3     3 0 7 my $class = shift;
49 3         10 my ($a, $b) = @_;
50              
51             # First decode the json if it is not already decoded
52 3         16 $a = $class->qorm_inflate($a);
53 3         24 $b = $class->qorm_inflate($b);
54              
55             # Now encode it in canonical form so that identical structures produce identical strings.
56             # Another option would be to use Test2::Compare...
57 3         12 $a = $class->CJSON->encode($a);
58 3         14 $b = $class->CJSON->encode($b);
59              
60 3         26 return $a cmp $b;
61             }
62              
63 3     3 0 15 sub qorm_affinity { 'string' }
64              
65             sub qorm_sql_type {
66 0     0 0 0 my $self = shift;
67 0         0 my ($dialect) = @_;
68              
69 0 0 0     0 if (my $stype = $dialect->supports_type('jsonb') // $dialect->supports_type('json')) {
70 0         0 return $stype;
71             }
72              
73 0   0     0 return $dialect->supports_type('longtext') // $dialect->supports_type('text');
74 0         0 die "Could not find usable type for json, no json type, no longtest, and no text";
75             }
76              
77             sub qorm_register_type {
78 2     2 0 5 my $self = shift;
79 2         6 my ($types, $affinities) = @_;
80              
81 2   33     13 my $class = ref($self) || $self;
82              
83 2   33     16 $types->{json} //= $class;
84 2   33     13 $types->{jsonb} //= $class;
85              
86 2         19 push @{$affinities->{string}} => sub {
87 2     2   17 my %params = @_;
88 2 50       15 return $class if $params{name} =~ m/json/i;
89 2 50       10 return $class if $params{db_name} =~ m/json/i;
90 2         18 return;
91 2         5 };
92             }
93              
94             1;