JSON-RPC 1.2 proposal

Date: 2007-12-27
Web site:(TODO)
Author: Roland Koebler (r dot koebler at yahoo dot de)
TODO:
  • adapt copyright-notice
  • create (separate) specifications for Service Descriptions and Extensions

Table of Contents


1   Preface

"JSON-RPC is a lightweight remote procedure call protocol. It's designed to be simple!" [JSON-RPC 1.0]

That's good.

But unfortunately, some useful things are missing in JSON-RPC 1.0, especially named parameters and some definitions about error-messages. The JSON-RPC 1.1 Working Draft on the other side somehow overshoots the mark and makes things much more complicated. This already led to several discussions on the JSON-RPC mailinglist [1].

The goal of this document is to propose a JSON-RPC-specification which enhances JSON-RPC 1.0, adds reasonable features from the 1.1WD, but still stays simple.

[1]The mailinglist recently moved from Yahoo to Google. It's current location is the JSON-RPC Google Group, but for older messages, you have to look into the old JSON-RPC Yahoo! Group.

1.1   Thoughts about RPC

In my opinion, RPC consists of several independent parts:

  1. data structure (how requests/responses/errors look like)
  2. serializer (i.e. JSON, XML, URI, ...)
  3. transport (i.e. Unix Domain Socket, TCP/IP, HTTP)
  4. proxy/dispatcher

Unfortunately, these parts are often not treated as independent, which results in unnecessarily complex results [2]. A RPC-specification should only define point 1 ("data structure"), and tell the user which serialization to use [3].

[2](Have you ever tried to run i.e. XML-RPC over Unix Domain Sockets? This does not work, because XML-RPC always uses http, although this would not be necessary.)
[3]Although requiring a specific serialization would not be absolutely necessary: It would also be possible to serialize XML-RPC-data-structures in JSON, or JSON-RPC-data-structures in XML. But I don't think that things like this are really useful.

1.2   Differences from Version 1.0

The main differences are:

  • client-server instead of peer-to-peer:
    This specification uses a client-server-architecture.
    V1.0 used a peer-to-peer-architecture where every peer was both server and client.
  • Transport independence:
    This specification doesn't define any transport-specific issues.
    V1.0 defined that exceptions must be raised if the connection is closed, and that invalid requests/responses must close the connection (and raise exceptions).
  • Named parameters added (OPTIONAL)

  • Optional parameters: defined that unspecified optional parameters SHOULD use a default-value.

  • Error-definitions added

  • System descriptions added

  • Extensions: moved "Class hinting" from the base specification to an extension.

  • principle of robustness added


2   Specification

2.1   Overview

JSON-RPC is a stateless, light-weight remote procedure call (RPC) protocol. It uses JSON (RFC 4627) as data format, and is transport-independent. It's designed to be simple!

2.2   Conventions

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.

Since JSON-RPC uses JSON, it shares the same type system as JSON (see http://www.json.org or RFC 4627). Whenever this document refers to any JSON type, the first letter is always capitalized: Object, Array, String, Number, True, False, Null.

All names (i.e. method-names or parameter-names) are case-sensitive.

Clients are the origin of Request objects. Servers are the origin of Response objects.

2.3   Compatibility

JSON-RPC 1.2 is nearly [4] compatible to JSON-RPC 1.0. This means that:

  • JSON-RPC 1.0-clients can communicate with JSON-RPC 1.2-servers.
  • JSON-RPC 1.2-clients can communicate with JSON-RPC 1.0-servers (as long as the additional features are not used).

Although the JSON-RPC 1.0-syntax has some weak points (e.g. the Response would be cleaner if it would only use result or error instead of both), it's worth keeping the syntax for compatibility reasons.

Besides, it's RECOMMENDED in JSON-RPC 1.2 to use the principle of robustness: "Be liberal in what you accept, and conservative in what you send". Details of this can be found in the sections Request and Response. This probably also enhances the compatibility with future versions.

[4]There are some differences which may cause incompatibility problems with JSON-RPC 1.0: The client-server- vs. peer-to-peer-structure, the transport-error-behaviour and the "class hinting" (see Differences from Version 1.0). But these "features" are probably rarely used, so JSON-RPC 1.2 should simply work with the vast majority of JSON-RPC 1.0 servers/clients. Nevertheless, if you need unconditional compatibility with JSON-RPC 1.0, you may of course emulate a peer-to-peer-structure (by running both client server), use the JSON-RPC 1.0 transport-error-behaviour and use the "class-hinting" extension.

2.4   Request (Procedure Call)

A remote procedure call is made by sending a Request to a remote service. The Request is expressed as a single JSON Object, with the following members:

method

A String containing the name of the procedure to be invoked.

Procedure names that begin with the word system followed by a period character (U+002E or ASCII 46) are reserved for system description / introspection.

params
An Array or Object (OPTIONAL), that holds the actual parameter values for the invocation of the procedure.
id

A Request identifier that SHOULD be a JSON scalar (String, Number, True, False, Null).

If id is Null, the Request is a Notification.

This id can be used to correlate a Response with its Request. The server MUST repeat it verbatim on the Response.

A Request MUST contain all 3 members.
A server however SHOULD also accept Requests where params and/or id is missing, and use an empty array for the missing params and Null for the missing id.

Every Request, except Notifications, MUST be replied to with a Response.

2.4.1   Notification (Procedure Call without Response)

A Notification is a special Request, with an id of Null and without Response. The server MUST NOT reply to a Notification.

Note that Notifications are unreliable by definition, since they do not have a Response, and so you cannot detect errors (like e.g. "Invalid params.", "Internal error.", timeouts or maybe even lost packets on the wire).

2.4.2   Parameters (positional and named)

Parameters for a procedure call can be specified by-position, or by-name (OPTIONAL).

  • by-position: params MUST be an Array, containing the parameters in the right order (like in JSON-RPC 1.0).

    This MUST be supported.

  • by-name: params MUST be an Object, containing the parameter-names and its values. The names MUST match exactly (including case) the names defined by the formal arguments. The order of the name/value-pairs is insignificant.

    This MAY be supported.

The position and name of a parameter is defined by the formal argument list of the procedure.

Mixing positional and named parameters in one call is not possible. (But could be added by an extension.)

2.4.3   Optional parameters

If the formal argument list of a procedure defines a default-value for a parameter, and the Request does not specify this parameter, the server SHOULD use this default-value for this parameter.

2.5   Response (Procedure Return)

When a remote procedure call is made, the service MUST reply with a Response (except for Notifications). The Response is expressed as a single JSON Object, with the following members:

result
The Value that was returned by the procedure. Its contents is entirely defined by the procedure.
This member MUST be Null if there was an error invoking the procedure.
error
An Error-Object containing error information about the fault that occurred before, during or after the call.
This member MUST be Null if there was no such fault.
id
The same id as in the Request it is responding to. If there was an error before detecting the id in the Request, it MUST be Null.

A Response MUST contain all 3 members. Both result and error MUST be specified. It's not allowed to omit one. If both result and error are Null, this means that there was no fault and the result is Null.

A client SHOULD however also accept Responses where result or error is omitted. The omitted field should be treated as if it was Null.

If the server does not completely understand a Request (e.g. because of additional members), it MAY reject the Request (with "Invalid Request.").

2.5.1   Error Object

When a remote procedure call fails, the Procedure Return object MUST contain the error member whose value is a JSON Object with the following members:

code
A Number that indicates the actual error that occurred. This MUST be an integer.
message
A String providing a short description of the error. The message SHOULD be limited to a concise single sentence.
data
Additional information, may be omitted. Its contents is entirely defined by the application (e.g. detailed error information, nested errors etc.).

Since JSON-RPC 1.0 did not define an error-object, clients MUST also accept errors which do not match to this.

The error-codes -32768 .. -32000 (inclusive) are reserved for pre-defined errors. Any error-code within this range not defined explicitly below is reserved for future use. [5]

code message Meaning
-32700 Parse error. Invalid JSON. An error occurred on the server while parsing the JSON text.
-32600 Invalid Request. The received JSON not a valid JSON-RPC Request.
-32601 Method not found. The requested remote-procedure does not exist / is not available.
-32602 Invalid params. Invalid method parameters.
-32603 Internal error. Internal JSON-RPC error.
-32099..-32000 Server error. Reserved for implementation-defined server-errors.
[5]The error-codes are the same as specified for XML-RPC at http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php

2.6   Examples

Syntax:

--> data sent to service
<-- data coming from service

Procedure Call with positional parameters:

--> {"method": "subtract", "params": [42, 23], "id": 1}
<-- {"result": 19, "error": null, "id": 1}

--> {"method": "subtract", "params": [23, 42], "id": 2}
<-- {"result": -19, "error": null, "id": 2}

Procedure Call with named parameters:

--> {"method": "subtract", "params": {"subtrahend": 23, "minuend": 42}, "id": 3}
<-- {"result": 19, "error": null, "id": 3}

--> {"method": "subtract", "params": {"minuend": 42, "subtrahend": 23}, "id": 4}
<-- {"result": 19, "error": null, "id": 4}

Notification:

--> {"method": "update", "params": [1,2,3,4,5], "id": null}

--> {"method": "foobar", "id": null}

Procedure Call of non-existent procedure:

--> {"method": "foobar", "params": [], "id": 10}
<-- {"result": null, "error": {"code": -32601, "message": "Procedure not found."}, "id": 10}

Procedure Call with invalid JSON:

--> {"method": "foobar, "params": "bar", "baz"]
<-- {"result": null, "error": {"code": -32700, "message": "Parse error"}, "id": null}

Procedure Call with invalid JSON-RPC:

--> [1,2,3]
<-- {"result": null, "error": {"code": -32600, "message": "Invalid JSON-RPC."}, "id": null}

--> {"method": 1, "params": "bar"}
<-- {"result": null, "error": {"code": -32600, "message": "Invalid JSON-RPC."}, "id": null}

2.7   System Description

Procedure names that begin with system. are reserved (see Request (Procedure Call)) for system description / introspection, and SHOULD not be used for anything else.

The Service Descriptions are defined in a related specification.

All Service Descriptions are OPTIONAL.

2.8   Extensions

There may be extensions, specified in related specification. (e.g. for: class-hinting, circular references, DateTime etc.)

All extensions are OPTIONAL.


Copyright (C) 2007 by ...

This document and translations of it may be used to implement JSON-RPC, it may be copied and furnished to others, and derivative works that comment on or otherwise explain it or assist in its implementation may be prepared, copied, published and distributed, in whole or in part, without restriction of any kind, provided that the above copyright notice and this paragraph are included on all such copies and derivative works. However, this document itself may not be modified in any way.

The limited permissions granted above are perpetual and will not be revoked.

This document and the information contained herein is provided "AS IS" and ALL WARRANTIES, EXPRESS OR IMPLIED are DISCLAIMED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.