Hi, group!
I'm building webapps with Mojolicious and a DBIC backend. I've got all of
my relationships in place. I want to make use of Mojo::JSON's TO_JSON
capability with DBIC's Helper::Row::ToJSON. It's really fantastic!
...until I want to subclass my TO_JSON methods and have:
package ::Donor;
sub TO_JSON {
return {items => $self->items};
}
package ::Item;
sub TO_JSON {
return {donor => $self->donor};
}
There's infinite recursion here. I don't know how to get around it!
Perhaps I'm doing something wrong in my DBIC classes. But that's a
discussion for the DBIC group, so I digress...
Which leads me to a solution I found with Mojo::JSON!
sub _encode_values {
:
# Blessed reference with TO_JSON method
if (blessed $value && (my $sub = $value->can('TO_JSON'))) {
return 'null' if grep { $_ eq ref $value }
@{$mojo->{__TO_JSON_DEPTH}};
push @{$mojo->{__TO_JSON_DEPTH}}, ref $value;
my $to_json = _encode_values($mojo, $value->$sub($mojo));
pop @{$mojo->{__TO_JSON_DEPTH}} unless ref $to_json;
return $to_json;
}
:
}
sub json_ancestor {
my $self = shift;
return $self->{__TO_JSON_DEPTH}->[$_[0]] if $_[0] =~ /^-?\d$/;
return grep { $_ eq $_[0] } @{$self->{__TO_JSON_DEPTH}} if $_[0];
return @{$self->{__TO_JSON_DEPTH}};
}
This does two things!
1. It automatically prevents infinite recursion with no changes to your
existing DBIC Result classes! Does it also present unintended consequences?
2. It allows me to do this in my DBIC Result class:
package ::Donor;
sub TO_JSON {
my $self = shift;
my $mojo = shift;
my $json = {%{$self->next::method}};
$json->{items} = [$self->items] unless
$mojo->json_ancestor('Schema::Result::Item');
return $json;
}
package ::Item;
sub TO_JSON {
my $self = shift;
my $mojo = shift;
my $json = {%{$self->next::method}};
$json->{donor} = [$self->donor] unless
$mojo->json_ancestor('Schema::Result::Donor');
return $json;
}
How cool is that?!
So, is this something the Mojolicious community is interested in? Is this
a good idea? Or should we pawn the problem off to DBIC?
I read the Contributing guide and there's certainly some work for me to do
to contribute my code which I'll happily do if I get the declared 2/3
vote! :D
Thanks for reading! Looking forward to a response.
Stefan