User Tools

Site Tools


Simple JSON RPC on Perl

Now w/o error handling. You can use any transport. In the example I use memory.

json-rpc.pl
#!/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";

Out

{"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}

First PagePrevious PageBack to overviewNext PageLast Page