JSON-RPC 2.0 规范
发布日期:2013 年 1 月 4 日 00:00:00
初始日期:2010 年 3 月 26 日(基于 2009 年 5 月 24 日版本)
作者:JSON-RPC 工作组 json-rpc@googlegroups.com
1. 概述
JSON-RPC 是一种无状态的轻量级远程过程调用(RPC)协议。本规范主要定义了几种数据结构及其处理规则。它与传输方式无关,其概念可用于同一进程内、套接字、HTTP 或多种消息传递环境中。它使用 JSON(RFC 4627)作为数据格式,设计理念是简单易用!
2. 约定
本文档中 “必须(MUST)”、“不得(MUST NOT)”、“要求(REQUIRED)”、“应(SHALL)”、“不应(SHALL NOT)”、“宜(SHOULD)”、“不宜(SHOULD NOT)”、“推荐(RECOMMENDED)”、“可以(MAY)” 和 “可选(OPTIONAL)” 等关键词的含义遵循 RFC 2119 中的描述。
由于 JSON-RPC 使用 JSON,它具有相同的类型系统(参见http://www.json.org或 RFC 4627)。JSON 可表示四种基本类型(字符串、数字、布尔值和空值)和两种结构化类型(对象和数组)。本规范中 “基本类型(Primitive)” 指上述四种 JSON 基本类型中的任意一种,“结构化类型(Structured)” 指两种 JSON 结构化类型中的任意一种。本文档提及任何 JSON 类型时,首字母始终大写:对象(Object)、数组(Array)、字符串(String)、数字(Number)、布尔值(Boolean)、空值(Null)。“True” 和 “False” 也大写。
客户端和服务器之间交换的、用于各种匹配的所有成员名称都应视为区分大小写。术语 “函数(function)”、“方法(method)” 和 “过程(procedure)” 可视为同义词。
客户端定义为请求对象的发起方和响应对象的处理方。
服务器定义为响应对象的发起方和请求对象的处理方。
本规范的一个实现可以轻松同时充当这两种角色,面向不同客户端或同一客户端。本规范未涉及这一层面的复杂性。
3. 兼容性
JSON-RPC 2.0 的请求对象和响应对象可能无法与现有的 JSON-RPC 1.0 客户端或服务器协同工作。不过,区分这两个版本很容易,因为 2.0 版本始终有一个名为 “jsonrpc” 的成员,其字符串值为 “2.0”,而 1.0 版本没有。大多数 2.0 实现应考虑尝试处理 1.0 对象,即使不处理 1.0 版本中的对等通信和类提示方面的内容。
4. 请求对象
通过向服务器发送请求对象来表示一次 RPC 调用。请求对象包含以下成员:
jsonrpc:指定 JSON-RPC 协议版本的字符串。必须为 “2.0”。
method:包含要调用方法名称的字符串。以 “rpc” 开头并紧跟一个句点字符(U+002E 或 ASCII 46)的方法名称保留用于 RPC 内部方法和扩展,不得用于其他用途。
params:保存方法调用时使用的参数值的结构化值。此成员可以省略。
id:由客户端设置的标识符,如果包含,必须是字符串、数字或空值。如果未包含,则假定该请求为通知。该值通常不应为空值 [1],并且数字不应包含小数部分 [2] 。如果请求中包含该成员,服务器必须在响应对象中返回相同的值,此成员用于关联两个对象之间的上下文。
[1] 不建议在请求对象中使用空值作为 id 成员的值,因为本规范将空值用于标识未知的响应。此外,JSON-RPC 1.0 将空值用于通知的 id,这可能在处理时造成混淆。
[2] 小数部分可能存在问题,因为许多十进制分数无法精确表示为二进制分数。
4.1 通知
通知是没有 “id” 成员的请求对象。作为通知的请求对象表明客户端对相应的响应对象不感兴趣,因此无需向客户端返回响应对象。服务器不得回复通知,包括批量请求中的通知。
通知按定义是不可确认的,因为没有要返回的响应对象。因此,客户端不会知晓任何错误(例如 “参数无效”、“内部错误”)。
4.2 参数结构
如果存在,RPC 调用的参数必须以结构化值的形式提供,可以通过数组按位置传递,也可以通过对象按名称传递。
按位置传递:params 必须是一个数组,包含服务器预期顺序的值。
按名称传递:params 必须是一个对象,其成员名称与服务器预期的参数名称匹配。缺少预期名称可能会导致生成错误。名称必须与方法预期的参数完全匹配,包括大小写。
5. 响应对象
进行 RPC 调用时,除通知情况外,服务器必须回复一个响应。响应表示为单个 JSON 对象,包含以下成员:
jsonrpc:指定 JSON-RPC 协议版本的字符串。必须为 “2.0”。
result:调用成功时该成员是必需的。如果调用方法时发生错误,该成员一定不能存在。该成员的值由服务器上调用的方法确定。
error:发生错误时该成员是必需的。如果调用过程中未触发任何错误,该成员一定不能存在。该成员的值必须是 5.1 节中定义的对象。
id:该成员是必需的。它必须与请求对象中 id 成员的值相同。如果在请求对象中检测 id 时出错(例如解析错误 / 无效请求),它必须为空值。
result 成员和 error 成员必须包含其中一个,但不能同时包含。
5.1 错误对象
当 RPC 调用遇到错误时,响应对象必须包含 error 成员,其值是一个包含以下成员的对象:
code:表示发生的错误类型的数字。必须是整数。
message:提供错误简短描述的字符串。该消息应限制为简洁的一句话。
data:包含有关错误的其他信息的基本类型或结构化值。可以省略。该成员的值由服务器定义(例如详细的错误信息、嵌套错误等)。
从 - 32768 到 - 32000(包括)的错误代码预留给预定义错误。此范围内未在下文明确定义的任何代码预留给未来使用。这些错误代码与以下 URL 中为 XML-RPC 建议的代码几乎相同:http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php
| 代码 | 消息 | 含义 |
|---|---|---|
| -32700 | 解析错误 | 服务器接收到无效的 JSON。服务器在解析 JSON 文本时发生错误。 |
| -32600 | 无效请求 | 发送的 JSON 不是有效的请求对象。 |
| -32601 | 方法未找到 | 方法不存在 / 不可用。 |
| -32602 | 无效参数 | 无效的方法参数。 |
| -32603 | 内部错误 | JSON-RPC 内部错误。 |
| -32000 到 -32099 | 服务器错误 | 预留给实现定义的服务器错误。 |
其余范围可用于应用程序定义的错误。
6. 批量处理
为了同时发送多个请求对象,客户端可以发送一个包含请求对象的数组。
服务器应在处理完所有批量请求对象后,回复一个包含相应响应对象的数组。每个请求对象都应有一个响应对象,除非该请求对象是通知。服务器可以将批量 RPC 调用作为一组并发任务进行处理,以任意顺序和并行度处理它们。
批量调用返回的响应对象可以在数组中以任意顺序返回。客户端应根据每个对象中的 id 成员来匹配请求对象集和生成的响应对象集之间的上下文。
如果批量 RPC 调用本身无法被识别为有效的 JSON 或至少包含一个值的数组,服务器的响应必须是单个响应对象。如果要发送给客户端的响应数组中不包含任何响应对象,服务器一定不能返回空数组,而应不返回任何内容。
7. 示例
语法:
--> 发送到服务器的数据
<– 发送到客户端的数据
带位置参数的 RPC 调用:
--> {“jsonrpc”: “2.0”, “method”: “subtract”, “params”: [42, 23], “id”: 1}
<– {“jsonrpc”: “2.0”, “result”: 19, “id”: 1}
--> {“jsonrpc”: “2.0”, “method”: “subtract”, “params”: [23, 42], “id”: 2}
<– {“jsonrpc”: “2.0”, “result”: -19, “id”: 2}
带命名参数的 RPC 调用:
--> {“jsonrpc”: “2.0”, “method”: “subtract”, “params”: {“subtrahend”: 23, “minuend”: 42}, “id”: 3}
<– {“jsonrpc”: “2.0”, “result”: 19, “id”: 3}
--> {“jsonrpc”: “2.0”, “method”: “subtract”, “params”: {“minuend”: 42, “subtrahend”: 23}, “id”: 4}
<– {“jsonrpc”: “2.0”, “result”: 19, “id”: 4}
通知:
--> {“jsonrpc”: “2.0”, “method”: “update”, “params”: [1,2,3,4,5]}
--> {“jsonrpc”: “2.0”, “method”: “foobar”}
调用不存在的方法:
--> {“jsonrpc”: “2.0”, “method”: “foobar”, “id”: “1”}
<– {“jsonrpc”: “2.0”, “error”: {“code”: -32601, “message”: “Method not found”}, “id”: “1”}
带无效 JSON 的 RPC 调用:
--> {“jsonrpc”: “2.0”, “method”: “foobar, “params”: “bar”, “baz]}
<– {“jsonrpc”: “2.0”, “error”: {“code”: -32700, “message”: “Parse error”}, “id”: null}
带无效请求对象的 RPC 调用:
--> {“jsonrpc”: “2.0”, “method”: 1, “params”: “bar”}
<– {“jsonrpc”: “2.0”, “error”: {“code”: -32600, “message”: “Invalid Request”}, “id”: null}
批量 RPC 调用,无效 JSON:
--> [{“jsonrpc”: “2.0”, “method”: “sum”, “params”: [1,2,4], “id”: “1”},{“jsonrpc”: “2.0”, “method”}]
<– {“jsonrpc”: “2.0”, “error”: {“code”: -32700, “message”: “Parse error”}, “id”: null}
带空数组的 RPC 调用:
--> []
<– {“jsonrpc”: “2.0”, “error”: {“code”: -32600, “message”: “Invalid Request”}, “id”: null}
带无效批量(但非空)的 RPC 调用:
--> [1]
<– [{“jsonrpc”: “2.0”, “error”: {“code”: -32600, “message”: “Invalid Request”}, “id”: null}]
带无效批量的 RPC 调用:
--> [1,2,3]
<– [{“jsonrpc”: “2.0”, “error”: {“code”: -32600, “message”: “Invalid Request”}, “id”: null},{“jsonrpc”: “2.0”, “error”: {“code”: -32600, “message”: “Invalid Request”}, “id”: null},{“jsonrpc”: “2.0”, “error”: {“code”: -32600, “message”: “Invalid Request”}, “id”: null}]
批量 RPC 调用:
--> [{“jsonrpc”: “2.0”, “method”: “sum”, “params”: [1,2,4], “id”: “1”},{“jsonrpc”: “2.0”, “method”: “notify_hello”, “params”: [7]},{“jsonrpc”: “2.0”, “method”: “subtract”, “params”: [42,23], “id”: “2”},{“foo”: “boo”},{“jsonrpc”: “2.0”, “method”: “foo.get”, “params”: {“name”: “myself”}, “id”: “5”},{“jsonrpc”: “2.0”, “method”: “get_data”, “id”: “9”}]
<– [{“jsonrpc”: “2.0”, “result”: 7, “id”: “1”},{“jsonrpc”: “2.0”, “result”: 19, “id”: “2”},{“jsonrpc”: “2.0”, “error”: {“code”: -32600, “message”: “Invalid Request”}, “id”: null},{“jsonrpc”: “2.0”, “error”: {“code”: -32601, “message”: “Method not found”}, “id”: “5”},{“jsonrpc”: “2.0”, “result”: [“hello”, 5], “id”: “9”}]
批量 RPC 调用(全为通知):
--> [{“jsonrpc”: “2.0”, “method”: “notify_sum”, “params”: [1,2,4]},{“jsonrpc”: “2.0”, “method”: “notify_hello”, “params”: [7]}]
<– // 全为通知的批量调用不返回任何内容
8. 扩展
以 “rpc.” 开头的方法名称保留用于系统扩展,不得用于其他用途。每个系统扩展在相关规范中定义。所有系统扩展都是可选的。
版权所有 (C) 2007 - 2010 JSON-RPC 工作组
本文档及其翻译可用于实现 JSON-RPC,可以复制并提供给他人,也可以编写、复制、发布和分发对本文档进行评论、解释或辅助实现的衍生作品,无需任何限制,但前提是上述版权声明和本段内容包含在所有此类副本和衍生作品中。然而,本文档本身不得以任何方式修改。
上述授予的有限权限是永久性的,不会被撤销。