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

相关推荐
摘星编程2 小时前
MCP提示词工程:上下文注入的艺术与科学
人工智能·提示词工程·a/b测试·mcp·上下文注入
智海观潮8 小时前
Unity Catalog与Apache Iceberg如何重塑Data+AI时代的企业数据架构
大数据·人工智能·ai·iceberg·catalog
Nandeska10 小时前
二、CUDA、Pytorch与依赖的工具包
ai
思绪漂移13 小时前
阿里云 【免费试用】MCP 赋能可视化 OLAP 智能体应用
阿里云·云计算·agent·云原生数据库·mcp
大模型真好玩14 小时前
深入浅出LangChain AI Agent智能体开发教程(五)—LangChain接入工具基本流程
人工智能·python·mcp
NocoBase19 小时前
GitHub 上 Star 数量前 8 的开源 MCP 项目
开源·openai·mcp
裘乡20 小时前
一文入门 MCP(Model Context Protocol)
mcp
Lstmxx20 小时前
解放前端生产力:我如何用 LLM 和 Bun.js 构建一个 YApi to TypeScript 的自动化代码生成服务
前端·ai编程·mcp
裘乡20 小时前
MCP 进阶思考
mcp