# this is a simplistic example
# you probably want to use L<JSON::RPC::Common::Marshal::Text> instead for
# something like this.
use JSON::RPC::Common::Procedure::Call;
# deserialize whatever json text you have into json data:
my $req = from_json($request_body);
# inflate it and get a call object:
my $call = JSON::RPC::Common::Procedure::Call->inflate($req);
warn $call->version;
# this will create a result object of the correct class/version/etc
# "value" is the return result, regardless of version
my $res = $call->return_result("value");
# finally, convert back to json text:
print to_json($res->deflate);

This module provides abstractions for JSON-RPC 1.0, 1.1 (both variations) and 2.0 (formerly 1.2) Procedure Call and Procedure Return objects (formerly known as request and result), along with error objects. It also provides marshalling objects to convert the model objects into JSON text and HTTP requests/responses.

This module does not concern itself with the transport layer at all, so the JSON-RPC 1.1 and the alternative specification, which are very different on that level are implemented with the same class.

While JSON-RPC 1.0 and JSON-RPC 2.0 are beautifully simple, the JSON-RPC 1.1 working draft, is most definitely not. It is a convoluted protocol, and also demands a lot more complexity from the responders on the server side (server side introspection (system.describe), strange things relating to positional vs. named params...).

Unfortunately it appears that JSON-RPC 1.1 is the most popular variant.

Since the client essentially chooses the version of the RPC to be used, for public APIs I reccomend that all versions be supported, but be aware that a 1.1-WD server "MUST" implement service description in order to be in compliance.