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!
- It automatically prevents infinite recursion with no changes to your existing DBIC Result classes! Does it also present unintended consequences?
- 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