File Coverage

blib/lib/DBIx/Class/Helper/Row/ToJSON.pm
Criterion Covered Total %
statement 27 27 100.0
branch 7 8 87.5
condition 4 6 66.6
subroutine 7 7 100.0
pod 3 3 100.0
total 48 51 94.1


line stmt bran cond sub pod time code
1             package DBIx::Class::Helper::Row::ToJSON;
2             $DBIx::Class::Helper::Row::ToJSON::VERSION = '2.035000';
3             # ABSTRACT: Remove the boilerplate from your TO_JSON functions
4              
5 56     56   7037526 use strict;
  56         270  
  56         1862  
6 56     56   330 use warnings;
  56         145  
  56         2954  
7              
8 56     56   305 use parent 'DBIx::Class::Row';
  56         2732  
  56         393  
9              
10             __PACKAGE__->mk_group_accessors(inherited => '_serializable_columns');
11             __PACKAGE__->mk_group_accessors(inherited => '_unserializable_data_types');
12              
13             my $dont_serialize = {
14             text => 1,
15             ntext => 1,
16             blob => 1,
17             };
18              
19             sub _is_column_serializable {
20 42     42   282 my ( $self, $column ) = @_;
21              
22 42         853 my $info = $self->column_info($column);
23              
24 42 100       2083 if (!defined $info->{is_serializable}) {
25 11 100 66     51 if (defined $info->{data_type} &&
26             $self->unserializable_data_types->{lc $info->{data_type}}
27             ) {
28 1         16 $info->{is_serializable} = 0;
29             } else {
30 10         126 $info->{is_serializable} = 1;
31             }
32             }
33              
34 42         355 return $info->{is_serializable};
35             }
36              
37             sub serializable_columns {
38 14     14 1 22 my $self = shift;
39 14 50       374 if (!$self->_serializable_columns) {
40 14         2403 $self->_serializable_columns([
41             grep $self->_is_column_serializable($_),
42             $self->result_source->columns
43             ]);
44             }
45 14         463 return $self->_serializable_columns;
46             }
47              
48             sub TO_JSON {
49 14     14 1 7594 my $self = shift;
50              
51 14         57 my $columns_info = $self->columns_info($self->serializable_columns);
52              
53             return {
54             map +($_ => $self->$_),
55 14   66     2317 map +($columns_info->{$_}{accessor} || $_),
56             keys %$columns_info
57             };
58             }
59              
60             sub unserializable_data_types {
61 9     9 1 16 my $self = shift;
62 9 100       231 if (!$self->_unserializable_data_types) {
63 3         526 $self->_unserializable_data_types($dont_serialize);
64             }
65 9         277 return $self->_unserializable_data_types;
66             }
67              
68             1;
69              
70             __END__
71              
72             =pod
73              
74             =head1 NAME
75              
76             DBIx::Class::Helper::Row::ToJSON - Remove the boilerplate from your TO_JSON functions
77              
78             =head1 SYNOPSIS
79              
80             package MyApp::Schema::Result::KittenRobot;
81              
82             use parent 'DBIx::Class::Core';
83              
84             __PACKAGE__->load_components(qw{Helper::Row::ToJSON});
85              
86             __PACKAGE__->table('KittenRobot');
87             __PACKAGE__->add_columns(
88             id => {
89             data_type => 'integer',
90             is_auto_increment => 1,
91             },
92             kitten => {
93             data_type => 'integer',
94             },
95             robot => {
96             data_type => 'text',
97             is_nullable => 1,
98             },
99             your_mom => {
100             data_type => 'blob',
101             is_nullable => 1,
102             is_serializable => 1,
103             },
104             );
105              
106             1;
107              
108             This helper adds a JSON method like the following:
109              
110             sub TO_JSON {
111             return {
112             id => $self->id,
113             kitten => $self->kitten,
114             # robot => $self->robot, # <-- doesn't serialize text columns
115             your_mom => $self->your_mom, # <-- normally wouldn't but explicitly
116             # asked for in the column spec above
117             }
118             }
119              
120             =head1 METHODS
121              
122             =head2 _is_column_serializable
123              
124             $self->_is_column_serializable('kitten')
125              
126             returns true if a column should be serializable or not. Currently this marks
127             everything as serializable unless C<is_serializable> is set to false, or
128             C<data_type> is a C<blob>, C<text>, or C<ntext> columns. If you wanted to only
129             have explicit serialization you might override this method to look like this:
130              
131             sub _is_column_serializable {
132             my ( $self, $column ) = @_;
133              
134             my $info = $self->column_info($column);
135              
136             return defined $info->{is_serializable} && $info->{is_serializable};
137             }
138              
139             =head2 serializable_columns
140              
141             $self->serializable_columns
142              
143             simply returns a list of columns that TO_JSON should serialize.
144              
145             =head2 TO_JSON
146              
147             $self->TO_JSON
148              
149             returns a hashref representing your object. Override this method to add data
150             to the returned hashref:
151              
152             sub TO_JSON {
153             my $self = shift;
154              
155             return {
156             customer_name => $self->customer->name,
157             %{ $self->next::method },
158             }
159             }
160              
161             =head2 unserializable_data_types
162              
163             $self->unserializable_data_types
164              
165             Simply returns a hashref of data types that TO_JSON should not serialize.
166             Defaults to C<blob>, C<text>, or C<ntext>.
167              
168             If you wanted to allow serialization of text data types, you might override this
169             method to look like this:
170              
171             sub unserializable_data_types {
172             return {
173             blob => 1,
174             ntext => 1,
175             };
176             }
177              
178             =head1 AUTHOR
179              
180             Arthur Axel "fREW" Schmidt <frioux+cpan@gmail.com>
181              
182             =head1 COPYRIGHT AND LICENSE
183              
184             This software is copyright (c) 2020 by Arthur Axel "fREW" Schmidt.
185              
186             This is free software; you can redistribute it and/or modify it under
187             the same terms as the Perl 5 programming language system itself.
188              
189             =cut