JSON::RPC::Client - Perl implementation of JSON-RPC client


JSON-RPC documentation Contained in the JSON-RPC distribution.

Index


Code Index:

NAME

Top

JSON::RPC::Client - Perl implementation of JSON-RPC client

SYNOPSIS

Top

   use JSON::RPC::Client;

   my $client = new JSON::RPC::Client;
   my $url    = 'http://www.example.com/jsonrpc/API';

   my $callobj = {
      method  => 'sum',
      params  => [ 17, 25 ], # ex.) params => { a => 20, b => 10 } for JSON-RPC v1.1
   };

   my $res = $client->call($uri, $callobj);

   if($res) {
      if ($res->is_error) {
          print "Error : ", $res->error_message;
      }
      else {
          print $res->result;
      }
   }
   else {
      print $client->status_line;
   }

   


   # Easy access

   $client->prepare($uri, ['sum', 'echo']);
   print $client->sum(10, 23);




DESCRIPTION

Top

This is JSON-RPC Client. See http://json-rpc.org/wd/JSON-RPC-1-1-WD-20060807.html.

Gets a perl object and convert to a JSON request data.

Sends the request to a server.

Gets a response returned by the server.

Converts the JSON response data to the perl object.

JSON::RPC::Client

Top

METHODS

$client = JSON::RPC::Client->new

Creates new JSON::RPC::Client object.

$response = $client->call($uri, $procedure_object)

Calls to $uri with $procedure_object. The request method is usually POST. If $uri has query string, method is GET.

About 'GET' method, see to http://json-rpc.org/wd/JSON-RPC-1-1-WD-20060807.html#GetProcedureCall.

Return value is JSON::RPC::ReturnObject.

$client->prepare($uri, $arrayref_of_procedure)

Allow to call methods in contents of $arrayref_of_procedure. Then you can call the prepared methods with an array reference or a list.

The return value is a result part of JSON::RPC::ReturnObject.

   $client->prepare($uri, ['sum', 'echo']);

   $res = $client->echo('foobar');  # $res is 'foobar'.

   $res = $client->sum(10, 20);     # sum up
   $res = $client->sum( [10, 20] ); # same as above

If you call a method which is not prepared, it will croak.

Currently, can't call any method names as same as built-in methods.

version

Sets the JSON-RPC protocol version. 1.1 by default.

id

Sets a request identifier. In JSON-RPC 1.1, it is optoinal.

If you set version 1.0 and don't set id, the module sets 'JSON::RPC::Client' to it.

ua

Setter/getter to LWP::UserAgent object.

json

Setter/getter to the JSON coder object. Default is JSON, likes this:

   $self->json( JSON->new->allow_nonref->utf8 );

   $json = $self->json;

This object serializes/deserializes JSON data. By default, returned JSON data assumes UTF-8 encoded.

status_line

Returns status code; After call a remote procedure, the status code is set.

create_json_coder

(Class method) Returns a JSON de/encoder in new. You can override it to use your favorite JSON de/encoder.

JSON::RPC::ReturnObject

Top

call method or the methods set by prepared returns this object. (The returned JSON data is decoded by the JSON coder object which was passed by the client object.)

METHODS

is_success

If the call is successful, returns a true, otherwise a false.

is_error

If the call is not successful, returns a true, otherwise a false.

error_message

If the response contains an error message, returns it.

result

Returns the result part of a data structure returned by the called server.

content

Returns the whole data structure returned by the called server.

jsontext

Returns the row JSON data.

version

Returns the version of this response data.

JSON::RPC::ServiceObject

Top

RESERVED PROCEDURE

Top

When a client call a procedure (method) name 'system.foobar', JSON::RPC::Server look up MyApp::system::foobar.

http://json-rpc.org/wd/JSON-RPC-1-1-WD-20060807.html#ProcedureCall

http://json-rpc.org/wd/JSON-RPC-1-1-WD-20060807.html#ServiceDescription

There is JSON::RPC::Server::system::describe for default response of 'system.describe'.

SEE ALSO

Top

http://json-rpc.org/wd/JSON-RPC-1-1-WD-20060807.html

http://json-rpc.org/wiki/specification

AUTHOR

Top

Makamaka Hannyaharamitu, <makamaka[at]cpan.org>

COPYRIGHT AND LICENSE

Top


JSON-RPC documentation Contained in the JSON-RPC distribution.

##############################################################################
# JSONRPC version 1.1
# http://json-rpc.org/wd/JSON-RPC-1-1-WD-20060807.html
##############################################################################

use strict;
use JSON ();
use Carp ();

##############################################################################

package JSON::RPC::Client;

$JSON::RPC::Client::VERSION = '0.93';

use LWP::UserAgent;


BEGIN {
    for my $method (qw/uri ua json content_type version id allow_call status_line/) {
        eval qq|
                        sub $method {
                                \$_[0]->{$method} = \$_[1] if defined \$_[1];
                                \$_[0]->{$method};
                        }
                |;
    }
}



sub AUTOLOAD {
    my $self   = shift;
    my $method = $JSON::RPC::Client::AUTOLOAD;

    $method =~ s/.*:://;

    return if ($method eq 'DESTROY');

    $method =~ s/^__(\w+)__$/$1/;  # avoid to call built-in methods (ex. __VERSION__ => VERSION)

    unless ( exists $self->allow_call->{ $method } ) {
        Carp::croak("Can't call the method not allowed by prepare().");
    }

    my @params = @_;
    my $obj = {
        method => $method,
        params => (ref $_[0] ? $_[0] : [@_]),
    };

    my $ret = $self->call($self->uri, $obj);

    if ( $ret and $ret->is_success ) {
        return $ret->result;
    }
    else {
        Carp::croak ( $ret ? '(Procedure error) ' . $ret->error_message : $self->status_line );
    }

}


sub create_json_coder {
    JSON->new->allow_nonref->utf8;
}


sub new {
    my $proto = shift;
    my $self  = bless {}, (ref $proto ? ref $proto : $proto);

    my $ua  = LWP::UserAgent->new(
        agent   => 'JSON::RPC::Client/' . $JSON::RPC::Client::VERSION . ' beta ',
        timeout => 10,
    );

    $self->ua($ua);
    $self->json( $proto->create_json_coder );
    $self->version('1.1');
    $self->content_type('application/json');

    return $self;
}


sub prepare {
    my ($self, $uri, $procedures) = @_;
    $self->uri($uri);
    $self->allow_call({ map { ($_ => 1) } @$procedures  });
}


sub call {
    my ($self, $uri, $obj) = @_;
    my $result;

    if ($uri =~ /\?/) {
       $result = $self->_get($uri);
    }
    else {
        Carp::croak "not hashref." unless (ref $obj eq 'HASH');
        $result = $self->_post($uri, $obj);
    }

    my $service = $obj->{method} =~ /^system\./ if ( $obj );

    $self->status_line($result->status_line);

    if ($result->is_success) {

        return unless($result->content); # notification?

        if ($service) {
            return JSON::RPC::ServiceObject->new($result, $self->json);
        }

        return JSON::RPC::ReturnObject->new($result, $self->json);
    }
    else {
        return;
    }
}


sub _post {
    my ($self, $uri, $obj) = @_;
    my $json = $self->json;

    $obj->{version} ||= $self->{version} || '1.1';

    if ($obj->{version} eq '1.0') {
        delete $obj->{version};
        if (exists $obj->{id}) {
            $self->id($obj->{id}) if ($obj->{id}); # if undef, it is notification.
        }
        else {
            $obj->{id} = $self->id || ($self->id('JSON::RPC::Client'));
        }
    }
    else {
        $obj->{id} = $self->id if (defined $self->id);
    }

    my $content = $json->encode($obj);

    $self->ua->post(
        $uri,
        Content_Type   => $self->{content_type},
        Content        => $content,
        Accept         => 'application/json',
    );
}


sub _get {
    my ($self, $uri) = @_;
    $self->ua->get(
        $uri,
        Accept         => 'application/json',
    );
}



##############################################################################

package JSON::RPC::ReturnObject;

$JSON::RPC::ReturnObject::VERSION = $JSON::RPC::VERSION;

BEGIN {
    for my $method (qw/is_success content jsontext version/) {
        eval qq|
                        sub $method {
                                \$_[0]->{$method} = \$_[1] if defined \$_[1];
                                \$_[0]->{$method};
                        }
                |;
    }
}


sub new {
    my ($class, $obj, $json) = @_;
    my $content = ( $json || JSON->new->utf8 )->decode( $obj->content );

    my $self = bless {
        jsontext  => $obj->content,
        content   => $content,
    }, $class;

    $content->{error} ? $self->is_success(0) : $self->is_success(1);

    $content->{version} ? $self->version(1.1) : $self->version(0) ;

    $self;
}


sub is_error { !$_[0]->is_success; }

sub error_message {
    $_[0]->version ? $_[0]->{content}->{error}->{message} : $_[0]->{content}->{error};
}


sub result {
    $_[0]->{content}->{result};
}


##############################################################################

package JSON::RPC::ServiceObject;

use base qw(JSON::RPC::ReturnObject);


sub sdversion {
    $_[0]->{content}->{sdversion} || '';
}


sub name {
    $_[0]->{content}->{name} || '';
}


sub result {
    $_[0]->{content}->{summary} || '';
}



1;
__END__