Now w/o error handling. You can use any transport. In the example I use memory.
#!/usr/bin/env perl # --- Dispatcher, Server side package aRPCD; use strict; use warnings; use Scalar::Util qw(reftype); use Mojo::Util qw(dumper); use Mojo::JSON qw(encode_json decode_json); sub new { my $class = shift; my $self = { func => undef }; bless $self, $class; return $self; } sub add { my ($self, $key, $val) = @_; my %ret; $self->{func}->{$key} = $val; $self; } sub call { my ($self, $name, @args) = @_; my $subr = $self->{func}->{$name}; return undef unless $subr; $subr->(@args); } sub exist { my ($self, $name, @args) = @_; return undef unless $self->{func}->{$name}; 1; } sub error { my ($name, $id, $code, $message) = @_; $id ||= 1; $message ||= 'generic error'; my $body = { jsonrpc => "2.0", error => { code => $code, message => $message, }, id => $id }; encode_json($body); } sub result { my ($self, $id, $res) = @_; $id ||= 1; my $body = { jsonrpc => "2.0", result => $res, id => $id }; encode_json($body); } sub jcall { my ($self, $str) = @_; my $jreq = decode_json($str); my $method = $jreq->{method}; my $params = $jreq->{params}; my $id = $jreq->{id}; my $res; unless (reftype $params) { $res = $self->call($method, $params); } elsif (reftype $params eq 'ARRAY') { my @params = @{$params}; $res = $self->call($method, @params); } elsif (reftype $params eq 'HASH') { my %params = %{$params}; $res = $self->call($method, %params); } $self->result($id, $res); } 1; # --- Serializator, Client side package aRPCC; use strict; use warnings; use Scalar::Util qw(reftype); use Mojo::Util qw(dumper); use Mojo::JSON qw(encode_json decode_json); sub new { my ($class, $url) = @_; my $self = { url => $url }; bless $self, $class; return $self; } sub json { my ($self, $name, $params) = @_; my $id = 1; my $body = { jsonrpc => "2.0", method => $name, params => $params, id => $id }; encode_json($body); } 1; use strict; use warnings; use Mojo::JSON qw(j decode_json encode_json); use Mojo::Util qw(dumper); use Scalar::Util qw(reftype); sub plus { my (%args) = @_; my $n = $args{a} += $args{b}; { a => 1, n => $n }; } sub plus2 { my ($a, $b) = @_; $b ||= 0; $a += $b; } my $r = aRPCD->new; $r->add('plus' => \&plus); $r->add('plus2' => \&plus2); my $c = aRPCC->new; print $c->json('plus', { a => 12, b => 16 }), "\n"; print $c->json('plus', [[ 12, 16 ], "a"]), "\n"; print $c->json('plus', 12), "\n"; my $j = $c->json('plus', { a => 12, b => 3 }); print $r->jcall($j), "\n"; my $j2 = $c->json('plus2', [12, 3]); print $r->jcall($j2), "\n"; $j2 = $c->json('plus2', 12); print $r->jcall($j2), "\n";
{"id":1,"jsonrpc":"2.0","method":"plus","params":{"a":12,"b":16}} {"id":1,"jsonrpc":"2.0","method":"plus","params":[[12,16],"a"]} {"id":1,"jsonrpc":"2.0","method":"plus","params":12} {"id":1,"jsonrpc":"2.0","result":{"a":1,"n":15}} {"id":1,"jsonrpc":"2.0","result":15} {"id":1,"jsonrpc":"2.0","result":12}