This document is currently a working draft published with the intent of soliciting community feedback. Please send your comments and concerns to the public mailing-list JSON-RPC Yahoo! Group. Make sure you prefix the subject line with “1.1WD:”, as in “1.1WD: Comment on errors”.
This specification is designed to provide the developer with the information needed to implement the protocol on the client or server end of a communication bus.
JSON-RPC is a stateless and light-weight remote procedure call (RPC) protocol for inter-networking applications over HTTP. It uses JSON as the data format for of all facets of a remote procedure call, including all application data carried in parameters.
By leveraging HTTP, JSON-RPC allows implementations to immediately benefit from the widely deployed World Wide Web infrastructure that is well-documented and understood today. It introduces no new HTTP verbs or message header extensions. JSON-RPC relies on JSON for the format of the HTTP message bodies, which allows implementations to benefit from a simple and standard text format that has suitable representations for the most commonly used scalar and structured data types inapplications. It is being quickly and widely adopted for web applications, and for which libraries are readily available in several languages.
The general mechanism for a remote procedure call using JSON-RPC consists of a client establishing a connection with a service and then invoking one or more procedures provided by that service. A single remote procedure call begins life as a request sent from the client to the server. The call ends when the client subsequently receives a response from the server over the same connection. Another call on the same connection is only made once the previous call has ended.
The primary goals of this specification are to define the JSON-RPC 1.1 protocol in terms of:
JSON-RPC does not address security, correlation, reliability, sessions management, state management and many other features that may be found in other RPC protocols or distributed systems. Developers are instead encouraged to employ features of HTTP and related Internet technologies that can offer some of these features in an equally compelling, robust and satisfying manner. Some features may be defined as extensions by other specifications.
The following list (non-comprehensive) summarizes the general changes that have been applied to version 1.0:
Content-Type
for JSON-RPC.version
member to Procedure Call and Procedure Return objects.The key words MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, SHOULD NOT, RECOMMENDED, MAY and OPTIONAL in this document are to be interpreted as described in RFC 2119.
An implementation is not compliant if it fails to satisfy one or more of the MUST requirements for the protocols it implements. An implementation that satisfies all of the MUST and all of the SHOULD requirements for its features is said to be unconditionally compliant; one that satisfies all of the 'must' requirements but not all of the SHOULD requirements for its features is said to be conditionally compliant.
Below is a summary of some terminology used in this documentation that can help in disambiguation of commonly applied and therefore often overloaded terms:
JSON-RPC shares the same type system as JSON to specify all value components of a call. In its abstract form (grammatic and syntatic details aside), JSON can represent four primitive types—String, Number, Booleans, and Null—and two structured types—Object and Array—that are briefly defined here:
true
or false
.null
.For the remainder of this document, it is expected that the reader has some familiarity with the basic syntax of JSON text. Otherwise, consult the JSON specification (RFC 4627) for further details.
This document also uses a specific convention to refer to any JSON type. Wherever a JSON type is mentioned, the first letter is always capitalized and the whole word appears in its root form (never in its plural form).
A remote procedure call is made by sending a request to a remote service using either HTTP POST or HTTP GET. How and where the call is encoded within the HTTP message depends on the HTTP method that is employed. In the case of HTTP POST, the procedure call is carried in the body of the HTTP message whereas in the case of HTTP GET, it is expressed along the path and query components of the HTTP Request-URI.
Suppose that a service exposes a procedure named sum
that takes two Number parameters,
as in sum(a, b)
, and returns their sum.
The HTTP POST to call this procedure call would be as follows:
POST /myservice HTTP/1.1 User-Agent: Wget/1.6 Host: www.example.com Content-Type: application/json Content-Length: 181 Accept: application/json { "version" : "1.1", "method" : "sum", "params" : [ 17, 25 ] }
In this example, the method being targeted is provided by a
service located at http://www.example.com/myservice
.
The call is expressed as a JSON Object in the body of the HTTP
POST message. The version
member of this object tells
the receiver the version of the JSON-RPC protocol being used by the
client. The method
member indicates the procedure
being invoked, which is sum in this example. Finally,
the params
member contains a JSON Array that lists
the parameters (in order) to be supplied to the procedure.
The same invocation is shown here using HTTP GET:
GET /myservice/sum?a=17&b=25 HTTP/1.1 User-Agent: Wget/1.6 Host: www.example.com Accept: application/json
There are two distinctions from the HTTP POST version that are improtant to note. First, an HTTP GET targeting a procedure on a JSON-RPC service is largely indistinguishable from a regular HTTP GET transaction. For this reason, there is no mention of of the JSON-RPC protocol version being used. Second, the entire call is encoded in the HTTP Request-URI. The procedure to invoke is appended to the location of the service, such that it appears as the last component of the URI path component. The call parameters appear as the query component and are named after the formal arguments of the target procedure.
Regardless of whether a remote procedure call is made using HTTP GET or POST, the HTTP request message MUST specify the following headers:
User-Agent
MUST be specified.Content-Type
MUST be specified and SHOULD read application/json
.Content-Length
MUST be specified and correct according
to the guidelines and rules laid out in Section 4.4, “Message Length”,
of the HTTP specification.Accept
MUST be specified and SHOULD read application/json
.When using HTTP POST, the call is expressed in the HTTP request body as a JSON Object that carries the following members:
"1.1"
for this member.system
followed by a period character (U+002E
or ASCII 46) are reserved. In other words, a procedure named system.foobar
is considered to have reserved semantics.
proc
to reflect the procedure in RPC, but
is being left as method
for sake of compatibility. One could permit
both, but that could unnecessarily increase complexity.
In the text of this document, however, I have tried to stick to the term procedure.
If anyone spots any use of the word method, except references to the
membermethod
,
then please let me know.Unless a call is for notification purposes only, bearing one-way semantics, it MUST be replied to with a response.
Parameters for a procedure call can be identified by their name, position, or both. The name and position of a parameter is defined by the formal argument list of the target procedure. The first position is zero and increments by one for each subsequent formal argument.
A client can specify parameters by-name, by-position or both using a JSON Object as the value for the params member. Each member of this object becomes a candidate parameter for the call. If the name of the object member consists entirely of decimal digits (0-9) then it identifies the parameter by its position in the formal argument list. In all other instances, the member name identifies the parameter by its name and MUST match exactly (including in case) the name defined by the formal argument.
Suppose a remote procedure called sum that defines three formal arguments called
a
, b
and c
.
Suppose further that a
comes first in the argument list, b
second and c
third. The following example shows how this procedure would be called using named parameters in an HTTP POST transaction (the
headers have been omitted from all examples in this section for sake of brevity):
{ "version" : "1.1", "method" : "sum", "params" : { "a" : 12, "b" : 34, "c" : 56 } }
Since parameters are identified by their name, the order is insignificant. The same MAY be expressed with parameters appearing in a different order than which is defined by the formal argument list:
{ "version" : "1.1", "method" : "sum", "params" : { "b" : 34, "c" : 56, "a" : 12 } }
A client MAY choose to send all or some of the paramters by-position, in or out
of sequence. The example
below shows the same call being expressed with parameters
a
and
b
named after their positions
in the formal argument list:
{ "version" : "1.1", "method" : "sum", "params" : { "1" : 34, "c" : 56, "0" : 12 } }
If a client chooses to send parameters exclusively by their position, then it MAY
use a JSON Array for the params
member of the Procedure Call object as a terser
method:
{ "version" : "1.1", "method" : "sum", "params" : [ 12, 34, 56 ] }
A server MUST accept all forms of parameter expressions described in this section. The last case, where parameters are sent in an array, was the only one supported in JSON-RPC 1.0. Servers conforming to JSON-RPC 1.1 can therefore continue to support calls from existing JSON-RPC 1.0 clients.
If the value of the params member is any other type except JSON Object or Array, then the server MUST reject the call with an error.
params
member
is neither JSON Object or Array.
Calls that identify all parameters exclusively by-name are RECOMMENDED over any positional parameters for the following reasons:
The Null value MAY be used as the value of any parameter and MUST be taken to mean that the parameter is not being supplied for the call.
Client implementations SHOULD strive to order the members of the Procedure Call
object such that the server is able to employ a streaming strategy to process the contents.
At the very least, a client SHOULD ensure that the version
member
appears first and the params
member last.
An example how this can be an advantage is
where a client tries to invoke a procedure that does not exist on the target service. The server can then skip to the end and issue an error as soon as it reads
the value of the method
member and finds it to be in error.
params
member appears before method
.When using HTTP GET, the target procedure and parameters for the call are entirely expressed within the Request-URI of the HTTP message. The target procedure MUST appear as the last component of the Request-URI path component. The procedure's name MUST therefore be preceded by a forward-slash (U+002F or ASCII 47) but MUST NOT end in one.
The parameters are placed in the query component (as defined in
RFC 3986) of the Request-URI, which is then formatted using the same scheme as defined
for HTML Forms with
the get
method.
Each parameters consists of a name/position and value pair that is separated by
the equal sign (U+003D or ASCII 61) and parameters themselves are separated by an
ampersand (U+0026 or ASCII 38):
name1=value1&name2=value2&name3=value3…
A client MAY send the parameters in a different order than in which the formal argument list of the target procedure defines them.
The client MUST NOT use the JSON syntax for the parameter values. All values MUST be plain text and observe the escaping rules defined for the query component of the URL. After decoding, the server MUST treat all values as if they were sent as JSON String values. The server MAY then perform conversions at its discretion (on a best-attempt basis) if the formal arguments of the target procedure expects other non-String values. This specification does not define any conversion rules or methods.
Parameters named identically on the query string MUST be collapsed
into an Array of String values using the same order in which they appear in the query string and
identified by the repeating parameter name. For instance, the following query string specifies two parameters only,
namely scale
and city
:
city=london&scale=farenheit&city=zurich&city=new+york
The parameter scale
has the single String value of "farenheit"
whereas
city
is an Array of String values equivalent to the JSON text [ "london", "zurich", "new york" ]
.
It is specifically not possible to send parameters of type Object using HTTP GET.
Due to semantics and therefore requirements of HTTP GET, only procedures that are considered safe and idempotent MAY be invoked using HTTP GET. An explanation of what is considered safe and idempotent is provided in Section 9.1 (Safe and Idempotent Methods) of HTTP 1.1 specificiation. A server SHOULD provide a means (through a configuration file, for example) for a service to indicate which of its procedures are safe and idempotent in order to be callable using HTTP GET. In the absence of such means on the other hand, the server MUST allow invocations using HTTP POST only.
A server MUST respond with an error if a client attempts to invoke a procedure that has not been designated by the service as safe for call using HTTP GET.
A procedure callable using HTTP GET SHOULD also be callable using HTTP POST.
The choice of the HTTP method for a remote procedure call depends on the consequences of calling the procedure as well as the benefits afforded by each of the two HTTP methods. In general, any remote procedure call can be made using HTTP POST, but some benefits
HTTP GET can be particularly useful when:
Conforming implementations MUST treat procedure and parameter names as being case-sensitive such the names bar
and BAR
would be
seen as two distinct entities.
The parity of a procedure call is defined by how closely it matches the target procedure's formal definition and argument list. A call is on full parity with the target procedure when it meets all of the following conditions:
Note that when parameters are named by-position or by-name, their sequence does not change or contribute to the parity of the call. A call can have full parity with its procedure even if the parameters were not sent in the sequence of the formal argument list.
A server SHOULD try to adapt a call such that it has the greatest chance of succeeding by making the following adjustments for the actual invocation:
When a remote procedure call is made, the service MUST reply with a response whether the invocation was successful or not.
When the call is made using HTTP POST, the HTTP status code for a successful result MUST be 200.
When the call is made using HTTP GET, the HTTP status code for a successful result SHOULD be 200. If the HTTP GET call requested cache validation as well, the response MAY be 304 (Not Modified). The use of status codes generally related to redirection (e.g., 302 “Found” or 301 “Moved Permanently”) of HTTP GET transactions is not strictly prohibited, but service providers are RECOMMENDED instead to use public documentation and communication methods to advertise the relocation of a service.
Clients SHOULD be prepared to handle a status code of 401 (Unauthorized) resulting from an authentication challenge when a call is sent anonymously.
Unless noted otherwise, a status code of 500 (Internal Server Error) MUST be used under the following conditions:
Regardless of the HTTP method used to make the remote procedure call, the HTTP response message MUST specify the following headers:
Content-Type
MUST be specified and SHOULD read application/json
.Content-Length
MUST be specified and correct according
to the guidelines and rules laid out in Section 4.4, “Message Length”,
of the HTTP specification.Regardless of the HTTP method used to make the remote procedure call, the response body MUST be a JSON Object that carries the following properties or members:
id
member
of Procedure
Call object to which the response corresponds. This member is maintained
for backward compatibility with version 1.0 of the specification where it was used
to correlate a response with its request. If the id
member was
present on the request, then the server MUST repeat it verbatim on the response."1.1"
for this member. The absence of this member
can effectively be taken to mean that the remote server implement version 1.0 of
the JSON-RPC protocol.
Only one of result
or error
members MUST be specified, but never both. If both are missing, then the Procedure Return should be treated
as if it had the value Null.
HTTP/1.1 200 OK Connection: close Content-Length: 23 Content-Type: application/json Date: Sat, 08 Jul 2006 12:04:08 GMT Server: Microsoft-IIS/6.0 { "version" : "1.1", "result" : 42 }
When a remote procedure call fails, the Procedure Return object MUST contain the error
member whose value is a JSON Object with the following properties
members:
"JSONRPCError"
.{ "version" : "1.1", "error" : { "name" : "JSONRPCError", "code" : 123, "message" : "An error occurred parsing the request object.", "error" : { "name" : "JSONError", "message" : "Bad array", "at" : 42, "text" : "{\"id\":1,\"method\":\"sum\",\"params\":[1,2,3,4,5}"} } }
The following table lists the errors codes defined by this specification:
code | Example Message | Meaning |
---|---|---|
000 | Server error | A general error occurred on the server prior to procedure invocation on the service. |
000 | Parse error | An error occurred on the server while parsing the JSON text comprising the procedure call. |
000 | Bad call | The procedure call is not valid. |
000 | Call member out of sequence |
The server refuses to process the call because a member is not in the required sequence.
For example, the params member of the Procedure Call object appeared before version or
method members. |
000 | Service error | The call is valid, but a general error occurred during the procedure invocation. |
000 | Procedure not found | The call is valid but the procedure identified by the call could not be located on the service. |
The processing model for the treatment of a remote procedure call is outlined as follows:
A JSON-RPC service MUST, at a mimum, support a procedure called system.describe
.
The result of calling this procedure without any parameters MUST be a
Service Description
object as described in the next section.
A service description is a JSON Object with the following members or properties:
"1.0"
for conforming implementations."2.5"
to mean a major version of 2 and a minor version
of 5. The use and interpretation of the version number is left at the discretion
of the applications treating the Service Description.summary
has
any useful purpose in a service description. There is the help
member to serve a similar purpose anyhow.
Also, without this member being typed as Object, it is difficult to imagine how to
communicate the language of the text unless one includes a language
member (which starts to make things messy).http
or https
. Although this value is optional, it is highly RECOMMENDED that a service always publish its address so that a service description obtained
indirectly can be used nonetheless to locate the service.
A service SHOULD NOT include the system.describe
procedure in its description as it is assumed that all conforming services MUST support it.
A procedure description is a JSON Object with the following members and properties:
summary
has
any useful purpose in a service procedure description. There is the help
member to serve a similar purpose anyhow.
Also, without this member being typed as Object, it is difficult to imagine how to
communicate the language of the text unless one includes a language
member (which starts to make things messy).true
for the procedure to be considered idempotent."any"
. In either case, the elements
of the array MUST be ordered after the formal argument list of the procedure being
described. If this member is missing or the Null value then the procedure does not
expect any parameters."any"
.A procedure description is a JSON Object with the following members and properties:
"any"
.
The type
member of the Procedure Parameter Description MAY be one of
the following String values:
"bit"
"num"
"str"
"arr"
"obj"
"any"
"nil"
If another String value is found then it must be treated the same
as "any"
.
The "nil"
string MUST NOT be used to describe the type of a procedure's
formal argument. Rather, it is strictly reserved to denote the return type of a procedure
that is not expected to produce a result. In other words, the result
member of the
Procedure Return object resulting from a call to such procedure is
not interesting because it will always be the Null value.
It is valid for a call to supply the Null value for any parameter no matter how it is typed in its description.
Below is an example of Service Description object that describes a fictious DemoService
service that resides at the address http://www.example.com/service
and which publishes
a single procedure called sum
with two Number parameters, namely a
and b
,
and which returns a Number result.
{ "name" : "DemoService", "id" : "urn:uuid:41544946-415a-495a-5645-454441534646", "summary" : "A simple demonstration service.", "help" : "http://www.example.com/service/index.html", "address" : "http://www.example.com/service", "procs" : [ { "name" : "sum", "summary" : "Sums two numbers.", "help" : "http://www.example.com/service/sum.html", "params" : [ { "name" : "a", "type" : "num" }, { "name" : "b", "type" : "num" } ], "return" : { "type" : "num" }, { "name" : "time", "summary" : "Returns the current date and time in ISO 8601 format.", "help" : "http://www.example.com/service/time.html", "return" : { "type" : "string" } ] }
The summary
members of the Service Description and Procedure Description objects
contain human-readable text. A service MAY use the
Accept-Language header from the HTTP request message to deliver a localized
text for its String value. Likewise, the URL for the help
members MAY
also point a page that contains the localized documentation. However, the documentation
at the URL SHOULD also provide hyperlinks to the documentation in other languages
if the translations are available.
In JSON-RPC, service, procedure, parameters identifiable by name. The names of all these artifacts SHOULD only include:
All other characters in a name, although not technically excluded here, could severely limit the reach of the service and its procedures given certain environments, scenarios and especially programming languages.
Objects defined in this specification (Procedure Call, Procedure Return, Error)
MAY contain additional members not specifically
mentioned. Such
member names SHOULD be prefixed with the Dollar sign (U+0024 or ASCII 36), as in $extension
.
x-extension
, the Dollar sign seems like a more natural
and appropriate fit for JSON-RPC. Should we really be caring about the JavaScript/JSON
heritage in a communication protocol? One downside of using Dollar sign is that
it reserved in the Query component of the
URI Generic Syntax (RFC 2396).
It is worth noting that JSON-RPC is limited by the inability to represent cyclic object graphs in JSON text. Therefore implementations SHOULD take care that parent-child, sibling and cross-reference relationships result in error at the client end when making the remote procedure call or server end when responding with the result of the call. There are two possible ways to control this:
As soon as either configured limit is breached, the client or server fail the call with an error.