JSON-RPC 控制接口速查(2.0 规范)
依据 JSON-RPC 2.0 公开规范(jsonrpc.org)整理,各软件/设备的具体方法名与参数以其接口文档为准。
从一次对接扯皮说起
展厅项目里,中控要驱动一套第三方播控软件。对方给了份接口文档,写着”支持 JSON-RPC”,你照着发了个 play 过去,服务端却一声不吭。你以为软件挂了,抓包一看请求发出去了、TCP 也通,就是没回。折腾半天才发现:你发的报文漏了 id 字段,按 JSON-RPC 规范这就成了”通知”,服务端收到照做但规定不许回复。这种坑不是软件的锅,是没吃透协议那几条硬规矩。JSON-RPC 简单到一张纸能讲完,可正因为简单,字段少一个、类型错一处,现象就诡异。这篇把请求/响应/通知/批量的结构和那几个标准错误码讲透,附上能直接核对的报文,让你对接时一眼看出问题出在哪头。
JSON-RPC 是什么
JSON-RPC 是一种轻量级、传输无关的远程过程调用(RPC)协议,用 JSON 表达”调用某个方法、传哪些参数、返回什么结果”。当前主流版本为 2.0。
理解它,关键是对比 RESTful 风格接口。REST 以资源为中心,你操作的是一个个 URL(GET /player/status、POST /playlist),用 HTTP 动词表达增删改查。JSON-RPC 反过来,以方法为中心,你就是在”远程调一个函数”——play、setVolume、seek,名字即语义,参数即入参,返回即结果。对控制类接口这更顺手:展厅要的就是”播放""暂停""跳到第几秒”这种动作指令,硬套成资源 CRUD 反而别扭。
它还有个大优点是传输无关:JSON-RPC 只规定报文长什么样,不管你用什么管道送。它可以架在 TCP、HTTP、WebSocket 等任意能双向传字节流的通道上。展厅里常见做法是走 TCP 长连接或 WebSocket,中控和播控软件之间一条常连着的线,指令即发即到、状态即时回。许多知名系统(各类编辑器的语言服务、区块链节点 RPC)都用 JSON-RPC 做接口,正因为它简单、可读、易排错。
关键参数
| 项目 | 值 |
|---|---|
| 版本字段 | jsonrpc 必须为字符串 "2.0" |
| 传输 | 与传输无关(TCP / HTTP / WebSocket 等) |
| 数据格式 | JSON |
| 参数形式 | 数组(位置参数)或对象(命名参数) |
| 调用类型 | 请求(带 id)、通知(无 id)、批量(数组) |
id 类型 | 字符串、数字或 null(不建议用 null) |
| 响应互斥字段 | result 与 error 二者必居其一、不可并存 |
报文/数据格式:可核对的实例
下面每组报文都可直接对照,--> 是客户端(中控)发出,<-- 是服务端(播控软件)返回。
请求对象:含 jsonrpc、method(方法名)、可选 params、id(客户端标识,服务端须原样回传,用于把响应和请求对上号)。
--> { "jsonrpc": "2.0", "method": "setVolume", "params": [50], "id": 1 }
<-- { "jsonrpc": "2.0", "result": "ok", "id": 1 }
params 用数组是位置参数(第一个值对应第一个形参);也可以用对象传命名参数,可读性更好、顺序无关:
--> { "jsonrpc": "2.0", "method": "seek", "params": { "track": 3, "position": 12.5 }, "id": 2 }
<-- { "jsonrpc": "2.0", "result": { "track": 3, "position": 12.5, "state": "playing" }, "id": 2 }
通知(Notification):没有 id 的请求,表示”发了就不用管回复”。服务端绝不能对通知作出回复,即使处理出错也静默丢弃。开头那起扯皮就死在这——漏了 id 就成了通知。
--> { "jsonrpc": "2.0", "method": "play" }
(服务端不返回任何内容)
出错响应:请求带了 id 但处理失败,返回的是 error 而非 result,两者互斥。error 里含 code(错误码)、message(简述)、可选 data(附加信息):
--> { "jsonrpc": "2.0", "method": "loadPlaylist", "params": ["不存在的歌单"], "id": 3 }
<-- { "jsonrpc": "2.0", "error": { "code": -32602, "message": "Invalid params", "data": "playlist not found" }, "id": 3 }
批量调用(Batch):把多个请求放进一个数组一次发出,服务端返回对应的响应数组。注意三点:数组里的通知不产生响应;响应顺序不保证,客户端要按 id 自行匹配;整个批量数组本身格式非法(如空数组)时服务端返回单个错误对象。
--> [
{ "jsonrpc": "2.0", "method": "lightsOff", "id": 10 },
{ "jsonrpc": "2.0", "method": "curtainDown" },
{ "jsonrpc": "2.0", "method": "stopPlayback", "id": 11 }
]
<-- [
{ "jsonrpc": "2.0", "result": "ok", "id": 11 },
{ "jsonrpc": "2.0", "result": "ok", "id": 10 }
]
上面这组注意两处:中间那条 curtainDown 是通知(无 id),所以响应数组里没有它;返回的两条顺序是 11 在前 10 在后,跟发送顺序反了——这是允许的,客户端必须靠 id 对上号,别按数组下标硬匹配。
标准错误码:
| 错误码 | 含义 |
|---|---|
| -32700 | 解析错误(Parse error,非法 JSON,服务端读不出报文) |
| -32600 | 无效请求(Invalid Request,JSON 合法但不符合 RPC 结构) |
| -32601 | 方法不存在(Method not found,method 名对不上) |
| -32602 | 参数无效(Invalid params,参数个数/类型/内容不对) |
| -32603 | 内部错误(Internal error,服务端自身出错) |
-32768~-32000为协议保留区间;应用自定义错误码应避开该范围,放到这个区间之外去用。
展厅场景用法
- 播控软件控制:用
play/pause/seek/loadPlaylist/setVolume等方法远程驱动 SoftPlayer 播控软件,带id发、结果即时回传,中控据此更新界面状态。 - 批量编排一键化:把”关灯 + 落幕 + 停播”打包成一次批量调用,一个来回搞定,动作整齐、少了逐条往返的时间差。这跟 DMX512 灯光控制 里把通道值预存成场景一键触发是一个思路——都是把多步动作折叠成一次下发。
- 状态查询:调
getStatus类方法读当前播放位置、音量、在线状态,中控轮询或按需拉取。 - 即发即忘:用通知(无
id)下发无需确认的指令,如周期性心跳、低优先级动作,省掉响应开销。 - 跨设备统一层:中控侧用统一的 JSON-RPC 封装屏蔽各品牌设备的接口差异,对上层脚本只暴露一致的”调方法”接口,便于编排与自动化。
与 REST 对比选型
| 维度 | JSON-RPC | REST |
|---|---|---|
| 中心概念 | 方法(远程调函数) | 资源(URL + HTTP 动词) |
| 语义表达 | 动作类指令直接(play/seek) | 增删改查(CRUD)自然 |
| 批量操作 | 原生支持(batch 数组) | 需自行设计,无统一约定 |
| 传输 | 传输无关(TCP/WS/HTTP 皆可) | 强绑 HTTP |
| 双向/长连接 | 配 WebSocket 天然适合推状态 | 需额外机制(SSE/轮询/WebHook) |
| 通用工具生态 | 相对小众 | 浏览器/网关/缓存生态成熟 |
选型很直接:控制类、指令密集、要批量、要长连接推状态的场景选 JSON-RPC——展厅中控驱动播控/设备正是这类,动作语义直接、批量省往返、配 WebSocket 还能让设备主动推状态回来。对外提供资源型 API、要吃 HTTP 生态(缓存、网关、浏览器直连)的场景选 REST。两者不是谁取代谁,很多系统对内控制走 JSON-RPC、对外开放 API 走 REST,各用各的长处。
故障排查表
| 现象 | 可能原因 | 排查 / 解决 |
|---|---|---|
| 发了请求收不到任何回复 | 漏了 id,被当成通知 | 需要响应必须带 id,别用 null |
| 返回 -32700 | 报文不是合法 JSON(多逗号/引号错/截断) | 校验 JSON 语法,检查是否分包截断 |
| 返回 -32600 | JSON 合法但缺 jsonrpc/method 或结构不对 | 核对必填字段与类型,jsonrpc 须为 "2.0" |
| 返回 -32601 | 方法名拼写/大小写不符,或该版本不支持 | 对照接口文档核 method,确认版本支持 |
| 返回 -32602 | 参数个数、类型或内容不对 | 核对 params 是数组还是对象、每项类型 |
| 返回 -32603 | 服务端内部异常 | 查服务端日志,多为软件侧 bug 或环境问题 |
| 批量响应对不上号 | 按数组顺序硬匹配了响应 | 严格按 id 匹配,响应顺序不保证 |
| 长连接下部分响应丢失 | 粘包/拆包,多条报文黏在一起没正确分帧 | TCP 裸流需按行/长度自行分帧,或改用 WebSocket 消息边界 |
排查口诀:先看是不是通知问题(有没有 id),再看错误码指向哪层(解析/结构/方法/参数/内部),最后查传输分帧。 大量”没回复”的坑都死在 id 上。
进阶边界:分帧与安全
传输分帧要自己管:JSON-RPC 只定义单个报文长什么样,不管报文之间怎么分界。走裸 TCP 长连接时,多条报文会在字节流里黏一起(粘包)或被拆断(拆包),你得约定分帧方式——按换行符分(每条报文一行)、或前置长度头。走 WebSocket 就省心,它天然有消息边界,一条消息就是一条报文,这也是展厅长连接场景常选 WebSocket 的原因之一。
认证与安全:JSON-RPC 规范本身不含认证,鉴权靠承载它的传输层解决——HTTP 承载可用 Token/Basic Auth,TCP/WebSocket 可在握手阶段做鉴权或首包发令牌。展厅内网环境风险可控,但别把 RPC 端口直接暴露到公网,稳妥做法是把控制网划独立 VLAN、只让中控主机可达,物理隔离比协议层认证更靠谱。
动手检查清单
对接一套 JSON-RPC 控制接口前后,对着过一遍:
- 每条需要结果的请求都带了
id(唯一、非 null) -
jsonrpc字段是字符串"2.0",不是数字或漏写 -
params用数组还是对象,与接口文档一致 - 响应严格按
id匹配,不按数组下标硬对 - 批量调用里的通知不指望有响应
- 裸 TCP 场景已约定分帧方式(换行/长度头),或改用 WebSocket
- 自定义错误码避开 -32768~-32000 保留区间
- 控制网独立隔离,RPC 端口未暴露公网
小结
JSON-RPC 2.0 的全部要点其实就几条:jsonrpc:"2.0" + method + 可选 params + id 构成请求,有 id 是请求要回复、无 id 是通知不回复,result 和 error 二选一互斥,批量用数组、响应靠 id 对号、顺序不保证,五个标准错误码各指一层问题。它以”调方法”为中心、传输无关、原生支持批量,正好对上展厅中控驱动播控设备”动作密集、要批量、要长连接”的需求。真正的坑不在协议本身,而在那几条硬规矩——id 的有无、错误码的语义、裸 TCP 的分帧。摸清这几处,对接就从”扯皮”变成”照报文核对”。
延伸阅读:了解常配的长连接通道 WebSocket、对比 RESTful 接口 的资源风格,或看 DMX512 灯光控制 的场景化编排思路与全部设备协议速查。
需要把多套播控/设备的 JSON-RPC 接口编排成一键场景?了解 SoftControl 展厅中控系统与 SoftPlayer 播控软件,查看解决方案与落地案例,或直接联系我们聊聊你的定制需求。更多协议见设备协议库。