JSON-RPC 2.0 规范

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 作为数据格式,JSON 的类型系统包括四种原始类型(字符串、数字、布尔值和 null)以及两种结构化类型(对象和数组)。此文中提到的 JSON 类型首字母总是大写。

所有 Client 和 Server 之间交换的成员名称,特别是涉及匹配的,应该区分大小写。方法(method)和函数(function)、过程(procedure)可以视为同义词。

  • Client:请求对象的发起者和响应对象的处理者。
  • Server:响应对象的发起者和请求对象的处理者。

一个实现可以同时担任这两个角色,分别处理不同客户端或同一客户端的请求。

3. 兼容性

JSON-RPC 2.0 的请求对象和响应对象与现有的 JSON-RPC 1.0 客户端或服务器不兼容。2.0 版本始终包含名为 "jsonrpc" 的字段,值为 "2.0";而 1.0 版本没有这个字段。大多数 2.0 实现应该尝试处理 1.0 对象,尽管不支持点对点或类提示的特性。

4. 请求对象

RPC 调用通过发送一个请求对象给服务器表示。请求对象包含以下成员:

  • jsonrpc:指定 JSON-RPC 协议的版本。值必须为 "2.0"。
  • method:包含要调用的方法名称。方法名称以 "rpc" 开头的为系统保留,不能使用。
  • params:一个结构化的值,包含在方法调用时使用的参数。该字段可以省略。
  • id:由客户端指定的标识符,必须是字符串、数字或 null。如果省略该字段,则默认为通知类型。若包含,服务器返回的响应对象也必须包含该值,以便关联上下文。

4.1 通知

通知是没有 "id" 字段的请求对象。通知意味着客户端不关心响应,因此服务器不需要返回响应。通知不能确认,因此客户端无法得知是否发生错误。

4.2 参数结构

参数可以通过位置或名称传递:

  • 按位置传递:参数必须是一个数组,按照服务器预期的顺序传递。
  • 按名称传递:参数必须是一个对象,其中成员名称应与服务器预期的参数名称完全匹配。

5. 响应对象

服务器在处理请求时会返回一个响应对象,除非是通知类型。响应对象包含以下成员:

  • jsonrpc:指定 JSON-RPC 协议的版本。值必须为 "2.0"。
  • result:在成功时返回,表示方法的返回值。出错时,该字段不能存在。
  • error:在错误时返回,表示方法执行中的错误。没有错误时,该字段不能存在。包含错误详情的对象。
  • id:与请求对象中的 id 值相同。如果请求对象的 id 无法识别,返回 null。

5.1 错误对象

当 RPC 调用遇到错误时,响应对象中的 error 字段会包含以下信息:

  • code:一个整数,表示错误类型。
  • message:简短的错误描述。
  • data:一个可选的字段,包含错误的详细信息,值由服务器定义。

保留错误代码范围为 -32768 到 -32000,具体的错误代码定义如下:

错误代码 错误信息 含义
-32700 解析错误 无效的 JSON 格式。服务器解析 JSON 时出错。
-32600 无效的请求 发送的 JSON 不是有效的请求对象。
-32601 方法未找到 方法不存在或不可用。
-32602 参数无效 方法参数无效。
-32603 内部错误 服务器内部错误。
-32000 到 -32099 服务器错误 预留的服务器实现错误。

6. 批量请求

客户端可以同时发送多个请求对象,服务器将处理并返回相应的响应对象。批量请求的响应是一个数组,包含每个请求的响应对象。

  • 响应中的每个对象对应一个请求对象,通知类型的请求不会返回响应对象。
  • 批量请求可以并行处理,服务器处理顺序和并行度可以自由选择。
  • 如果批量请求本身无效,服务器返回一个单一的响应对象,而不是空数组。

7 示例

  1. 带位置参数的 RPC 调用

    json 复制代码
    --> {"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}
  2. 带命名参数的 RPC 调用

    json 复制代码
    --> {"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}
  3. 通知

    json 复制代码
    --> {"jsonrpc": "2.0", "method": "update", "params": [1,2,3,4,5]}
    --> {"jsonrpc": "2.0", "method": "foobar"}
  4. 调用不存在的方法

    json 复制代码
    --> {"jsonrpc": "2.0", "method": "foobar", "id": "1"}
    <-- {"jsonrpc": "2.0", "error": {"code": -32601, "message": "Method not found"}, "id": "1"}
  5. 无效的 JSON 调用

    json 复制代码
    --> {"jsonrpc": "2.0", "method": "foobar, "params": "bar", "baz]
    <-- {"jsonrpc": "2.0", "error": {"code": -32700, "message": "Parse error"}, "id": null}
  6. 无效请求对象的调用

    json 复制代码
    --> {"jsonrpc": "2.0", "method": 1, "params": "bar"}
    <-- {"jsonrpc": "2.0", "error": {"code": -32600, "message": "Invalid Request"}, "id": null}
  7. 批量请求,含无效的 JSON

    json 复制代码
    --> [
        {"jsonrpc": "2.0", "method": "sum", "params": [1,2,4], "id": "1"},
        {"jsonrpc": "2.0", "method": "foobar"}
    ]
    <-- {"jsonrpc": "2.0", "error": {"code": -32700, "message": "Parse error"}, "id": null}
  8. 带空数组的请求

    json 复制代码
    --> []
    <-- {"jsonrpc": "2.0", "error": {"code": -32600, "message": "Invalid Request"}, "id": null}
  9. 带无效元素的批量请求

    json 复制代码
    --> [1]
    <-- [
        {"jsonrpc": "2.0", "error": {"code": -32600, "message": "Invalid Request"}, "id": null}
    ]
  10. 无效的批量请求

    json 复制代码
    --> [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}
    ]
  11. 批量请求

    json 复制代码
    --> [
        {"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"}
    ]
  12. 批量请求(全是通知)

    json 复制代码
    --> [
        {"jsonrpc": "2.0", "method": "notify_sum", "params": [1,2,4]},
        {"jsonrpc": "2.0", "method": "notify_hello", "params": [7]}
    ]
    <-- // 所有通知批量没有返回内容

8 扩展

以 rpc. 开头的方法名称是为系统扩展保留的,必须避免用于其他目的。每个系统扩展在相关规范中定义。所有系统扩展都是可选的。

相关推荐
小白跃升坊7 小时前
Codex 增强部署:基于 Codex++ 接入 DeepSeek
ai·ai编程·codex·deepseek·ai coding·codex++
AlfredZhao7 小时前
GPT 省钱,不是别用最新模型,而是别浪费缓存
gpt·ai
doiito10 小时前
【Agent Harness】Gliding Horse 本体论系统设计:给 AI Agent 装上“语义大脑”
ai·rust·架构设计·系统设计·ai agent
小七-七牛开发者17 小时前
周一上线 | SpaceX 收购 Cursor、支付宝进入 AI 时代、DeepSeek 完成 500 亿元融资
ai·agent·token·glm·智谱·claudecode·ai coding·周一上线
doiito1 天前
【Agent Harness】为什么我把 JSON‑LD “编译成 DAG” 后,整个 Agent 平台立刻聪明了
ai·rust·架构设计·系统设计·ai agent
ServBay2 天前
Laravel Herd MCP 的替代,多语言与跨平台的 AI 本地开发选择
后端·ai编程·mcp
码哥字节2 天前
我把整个代码库喂给 Claude Code,工具超 50 个就静默丢失,这个坑太阴了
mcp·claude code·ai编程工具
xiezhr2 天前
折腾半小时,终于让AI 能直接帮我写飞书文档了
ai·飞书·ai agent·飞书cli·飞书文档
岳小哥AI2 天前
Claude Fable和Claude Mythos 5同时发布:注意力机制下愈加强大的AI大模型
ai·ai基础