3

I am trying to obtain JSON from a DBIx::Class::ResultSet and I get the exception

encountered object 'Sql2Json::Model::DB::Book=HASH(0x6014f88)', 
but neither allow_blessed, convert_blessed nor allow_tags settings are
enabled (or TO_JSON/FREEZE method missing)

The controller class is Books.pm:

package Sql2Json::Controller::Books;
use Moose;
use namespace::autoclean;
use JSON::XS;

BEGIN { extends 'Catalyst::Controller'; }

my $json = JSON::XS->new;

sub list : Local {
    my($self, $c) = @_;
    $c->stash(books_rs => $c->model('DB::Book'));
    $c->stash(books => [$c->stash->{books_rs}->search({}, {order_by => 'name ASC'})]);
    $c->stash(json_data => $json->convert_blessed->encode($c->stash->{books}));
    $c->forward('View::JSON');
}

__PACKAGE__->meta->make_immutable;

1;

According to this article is enough the encoding of blessed objects:

$json->convert_blessed->encode($c->stash->{books})

Do I missing somethig here?

  • 1
    The class of the object you want to serialize [needs to have](https://metacpan.org/pod/JSON::XS#$json-=-$json-%3Econvert_blessed-%28[$enable]%29) `TO_JSON` method. Does it? – zdim Oct 22 '18 at 07:18
  • No, it has no TO_JSON method. How sould it look like? – Kérdezösködő Indián Oct 22 '18 at 07:21
  • 1
    Something that serializes the object; see [Object Serialization](https://metacpan.org/pod/JSON::XS#OBJECT-SERIALISATION) in docs – zdim Oct 22 '18 at 07:26
  • 1
    Also, I think that the encoding will happen in `convert_blessed` (once `TO_JSON` exists and does the job of serializing its object) in which case there should be no call to `encode`. – zdim Oct 22 '18 at 07:28
  • I thought that the `sub TO_JSON { my $self = shift; return { class => 'Book', data => { %$self } }; }` is enough but not. It complains that the it encountered an object encountered object 'DBIx::Class::ResultSource::Table=HASH(0x5e21748). – Kérdezösködő Indián Oct 22 '18 at 07:37
  • I changed the method into this: `sub TO_JSON { my $self = shift; { book_id => $self->id, book_name => $self->name, } } ` and I get back a JSON, but it is ugly. `{ "json_data": "[{\"book_id\":\"490da28d-f80f-4a31-9177-4236bad7117d\",\"book_name\":\"Above and Beyond\"},{\"book_name\":\"If you ask me\",\"book_id\":\"38d0d3fc-a2ee-4b96-a677-4ede3f1a5dff\"},{\"book_name\":\"Leonardo da Vinci\",\"book_id\":\"630e1abf-aca4-4efb-8942-cd5020a5baa0\"}]" }` – Kérdezösködő Indián Oct 22 '18 at 07:41
  • 1
    OK, you got it. I don't know that it can be pretty. But it doesn't have to be, just think about how to best package it for the final purpose of that `JSON` (you can format it for reading eventually). On the other hand, there are modules for serialization, and I think that `FreezeThaw` returns a string (as needed). But I don't think it'll be pretty. – zdim Oct 22 '18 at 07:58

1 Answers1

1

Almost all the time, the best way to do this is using the get_inflated_column method of the rows returned from a query.

$books = $c->model('DB::Book');
$c->stash(json_data => [map {$_->get_inflated_columns} $books->all]);
$c->forward('View::JSON');