JSON RPC 2.0
For simple and powerful APIs
To my surprise a contender in the field of API protocols is yet unknown: JSON-RPC 2.0.
A standard since 2010, it is simple yet powerful but barely known amongst developers.
This article explains what it is, what makes it different and nice to work with and how to use it.
JSON-RPC 2.0 is a operation-oriented, transport-agnostic way to call methods on a server by using JSON-messages.
It supports batching of operations as well as so-called notifications aka "fire & forget".
The specification is rather short (921 words, including sample code and tables) and easy to implement and there's a variety of implementations available to choose from.
REST or RPC
In the recent years, we've made REST the gold standard of APIs.
It's nice in many cases, because the web is fundamentally about transferring and modifying resources. However, this is not always a good fit for an application.
Generally speaking, REST is an architecture pattern that defines a few constraints. These constraints aren't per se incompatible with RPC.
The big difference between the two styles is in the way you think and communicate between client and server:
In REST architectures you are concerned with resources and how to represent and modify them, while in RPC you are concerned with operations.
It's also worth mentioning that many people conflate "REST" with the HTTP implementation of REST, which isn't the only way to implement a REST-API.
But now, without further ado, let's see how different common tasks look like when implemented as REST or RPC:
|Get list of users||GET /users||users.list|
|Add new user||POST /users||users.create|
|Edit user||PUT /users/id||users.edit(id)|
|Delete user||DELETE /users/id||users.delete(id)|
|Calculate shipping fee||GET /orders/shipping/fee||orders.calculateShipping|
While one might choose to implement the last two rows differently in REST, it comes to show that for CRUD operations REST, especially HTTP-REST, is very obvious.
However when there is operations beyond those basic operations, REST isn't as obvious (is "login" a
/sessions or rather a separate operation on
For RPC, on the other hand, the freedom in how you name and structure your API might be overwhelming and can easily lead to inconsistency.
Also, depending on the implementation of RPC, you may not fully leverage the transport mechanism - but if you have to serve different transport mechanisms at the same time, this may not be a big downside either.
In short: REST is concerned with resources, RPC with operations - pick what suits your application and domain best.
JSON-RPC is an RPC-mechanism that uses JSON to encode the procedure call.
The specification is rather short and easy to digest.
It outlines how to call an operation on the server, how messages should look like and how to handle errors.
JSON-RPC is also transport-agnostic so you can transmit these messages by any means of your liking, e.g. HTTP, Web Sockets or messenger pidgeon depending on what's the fastest in your region.
It also allows another nice thing: Batch requests.
Batch requests means that a single message can contain multiple procedure calls in one batch and the response will contain the results for each of the calls, again as one batch. This really comes to shine, if all methods can work in parallel and thus the time until the response can be generated is limited to the slowest procedure.
Each message has to be valid JSON, containing the following elements:
jsonrpcwith a value of
2.0to mark this as a valid JSON-RPC 2.0 message
methodwith any string that identifies a valid procedure on the server
In addition to these two mandatory fields, there's two more optional ones:
idthat can be any string or integer (theoretically also
nullbut that's discouraged)
paramswhich can be a dictionary with parameter names and corresponding values or an array of unnamed parameters
The fact that
id is optional might be surprising at first, but the reason is rather simple:
If you need to call a procedure but you do not care about the result, you can send a so-called notification, which is a JSON-RPC message without the
The result of a JSON-RPC call with an ID will be answered by the server with a response containing the same ID.
A notification on the other hand (JSON-RPC call without ID) must never be getting a response from the server.
Response: Result or error
The response message format
Any response has two mandatory fields:
jsonrpcwith the value "2.0" to indicate a JSON-RPC v2.0 message
idwhich has the same value as the corresponding procedure call message
Success or error
Success or error responses are defined by two simple parameters in the response message:
resultfor successful calls
errorfor anything else
Only one of the two can be present in the response - it's either an error or a result.
result field can contain any data, including a dictionary, like the
params field. This holds the result of the called procedure.
Errors have a predefined format, but still allow for free-form data along the predefined fields.
The contents of the
error field should look like this:
codeis an (usually negative) integer (see below for reserved error codes)
messagea short (usually a single sentence) human-readable error message
datais a free-form field that can contain any data you'd like to pass along with the error response
There are predefined, reserved values for the
|-32700||Parse error||The message could not be parsed as JSON|
|-32600||Invalid message||The message is not a valid JSON-RPC request|
|-32601||Invalid method||The requested method does not exist or isn't available|
|-32602||Invalid params||The specified parameters are invalid or do not fit this method|
|-32603||Internal error||An internal server error has happened|
|-32000 to -32099||Implementation-defined||The JSON-RPC implementation can define these freely|
All other error codes can be used as application-specific error codes.
If this all sounded promising, you might be happy to find that not only the specification is rather short and comprehensible, but there's also many implementations to pick from.
Alternatively, especially when you use a subset of JSON-RPC 2.0 for internal purposes, implementing a custom client isn't that much effort.
The incomplete list of implementations covers you for most of the programming languages and use cases, so go ahead and try it out!