In yesterday’s report on the Language Server Protocol Support for Visual Studio, we mentioned that LSP is built on top of JSON-RPC 2.0. While it was created over a decade ago, JSON-RPC isn’t as well-known as SOAP or REST.
As the name implies, JSON-RPC is based on JSON and is used to make remote procedure calls. Philosophically, it differs from REST in that REST is data-centric; you write code mostly in terms of creating, modifying, and retrieving documents or records. An RPC design emphasizes calling functions that happen to exist in an external program. Of course those functions may manipulate documents, just as a REST call may do more than simply store some data.
In many ways JSON-RPC 2.0 can be thought of as a lightweight alternative to SOAP. Like SOAP it primarily concerns itself with what the messages actually look like. Other issues such as the transport layer (sdtio, sockets, HTTP, named pipes, etc.) are outside the scope of the protocol.
JSON-RPC can be used with asynchronous transports such as message queues. This is possible because each request is required to include a correlation id. This allows for more efficient communication than normal HTTP, as it permits multiple requests to be pending at the same time without the need for multiple connections.
Another useful feature of JSON-RPC is that it supports batch operations. That is to say, one message can contain an unlimited number of requests in an array. The response to these requests may occur in any order, singly or in an array, so again the use of the correlation id is important.
JSON-RPC also supports what it calls a “notification”. Notifications are like a request but they doesn’t not include a correlation id. As such, the server cannot respond to the message even if only to inform the client of an error. Thus, the use of notifications is discouraged.
Note: In the Language Server Protocol, Microsoft only uses notifications to cancel a pending request. And even then, the language server isn’t obligated to honor them.
Errors are reported using both a code and a message. Error codes in the -32768 to -32000 range are reserved by the protocol and used for exceptions such as “method not found” or “invalid parameter”.