From 73c846d0e213c5d2c81eb1aa8d0942948cfa4788 Mon Sep 17 00:00:00 2001 From: Tomas Cohen Arazi Date: Wed, 18 Jan 2017 15:37:42 -0300 Subject: [PATCH] Bug 17932: Add a TO_JSON method to Koha::Object(s) Bug 17927 fixes data types on the current REST endpoints. If you test those endpoints, you will notice trying to access them (for listing or retrieving single objects yields a data type error. Notably on booleans but also on integers. Integers fail due to https://rt.cpan.org/Ticket/Display.html?id=119904 but it needs some global solution until there's a DBD::mysql release backported to the supported distros. There's the option to use http://search.cpan.org/~frew/DBIx-Class-Helpers-2.033002/lib/DBIx/Class/Helper/Row/NumifyGet.pm to get the integer columns fixed as a workaround: __PACKAGE__->add_columns( borrowernumber => { data_type => 'integer', is_nullable => 0, is_numeric => 1, } ); I didn't find bug reports related to this (maybe because we don't use warnings everywhere) But I don't think is worth going such a heavy overhead. A similar situation takes place for Boolean values. They need to be prepared for JSON output. This could have been done using DBIx filters as pointed out by Martin: __PACKAGE__->filter_column( lost => { filter_to_storage => sub { $_[1] ? 1 : 0 }, filter_from_storage => sub { $_[1] ? Mojo::JSON->true : Mojo::JSON->false } } ); but this could have other consequences that are worth exploring on another bug (i.e. it would mean we need to take care of every place where this boolean data is used/set needs to handle this data types nicely. Such would be the case if we were a Mojo-only app, but we aren't. We use Koha::Obect(s) in the whole app. Period. This patch adds the need to specify on the schema files, columns that are actually boolean, because we have no way to detect them for now (i.e. they are all tinyint, but we use tinyint for non-boolean stuff too). So if this patch is accepted, we would need to specify boolean columns like this: __PACKAGE__->add_columns( '+lost' => { is_boolean => 1 } ); This patch adds a TO_JSON method for Koha::Object(s) to be used for serializing Koha::Object-derived objects into JSON strings. To test it (as Koha::Object(s) need to be instantiated) I provide tests on top of the Koha::Patron(s) classes in the followup patches. [1] Yes, we use TINYINT(1) for booleans, but from DBIC's perspective there's no way to read the (1) in runtime. Sponsored-by: ByWater Solutions --- Koha/Object.pm | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ Koha/Objects.pm | 12 ++++++++++++ 2 files changed, 67 insertions(+) diff --git a/Koha/Object.pm b/Koha/Object.pm index 709d7f2f41..010c8ef3e9 100644 --- a/Koha/Object.pm +++ b/Koha/Object.pm @@ -21,6 +21,7 @@ package Koha::Object; use Modern::Perl; use Carp; +use Mojo::JSON; use Koha::Database; use Koha::Exceptions::Object; @@ -190,6 +191,60 @@ sub unblessed { return { $self->_result->get_columns }; } +=head3 $object->TO_JSON + +Returns an unblessed representation of the object, suitable for JSON output. + +=cut + +sub TO_JSON { + + my ($self) = @_; + my $unblessed = $self->unblessed; + + return unless $unblessed; + + my $columns = Koha::Database->new->schema->resultset( $self->_type ) + ->result_source->{_columns}; + foreach my $col ( keys %{$columns} ) { + + if ( $columns->{$col}->{is_boolean} ) { # Handle booleans gracefully + $unblessed->{$col} + = ( $unblessed->{$col} ) + ? Mojo::JSON->true + : Mojo::JSON->false; + } + elsif ( _numeric_column_type($columns->{$col}->{data_type}) ) { + # TODO: Remove once the solution for + # https://rt.cpan.org/Ticket/Display.html?id=119904 + # is ported to whatever distro we support by that time + $unblessed->{$col} += 0; + } + } + return $unblessed; +} + +sub _numeric_column_type { + # TODO: Remove once the solution for + # https://rt.cpan.org/Ticket/Display.html?id=119904 + # is ported to whatever distro we support by that time + my ($column_type) = @_; + + my @numeric_types = ( + 'bigint', + 'integer', + 'int', + 'mediumint', + 'smallint', + 'tinyint', + 'decimal', + 'double precision', + 'float' + ); + + return ( grep { $column_type eq $_ } @numeric_types) ? 1 : 0; +} + =head3 $object->_result(); Returns the internal DBIC Row object diff --git a/Koha/Objects.pm b/Koha/Objects.pm index 92312066f8..86a5789466 100644 --- a/Koha/Objects.pm +++ b/Koha/Objects.pm @@ -252,6 +252,18 @@ sub unblessed { return [ map { $_->unblessed } $self->as_list ]; } +=head3 Koha::Objects->TO_JSON + +Returns an unblessed representation of objects, suitable for JSON output. + +=cut + +sub TO_JSON { + my ($self) = @_; + + return [ map { $_->TO_JSON } $self->as_list ]; +} + =head3 Koha::Objects->_wrap wraps the DBIC object in a corresponding Koha object -- 2.11.0