JSON-RPCについて

JSON-RPCについて調べた際のメモです。

特徴

JSON-RPC is a stateless, light-weight remote procedure call (RPC) protocol.

JSON-RPC 2.0 Specification

  • データのエンコードJSONを利用したRPC(Remote Procedure Call)1プロトコルの一種。
  • レスポンスを期待しない「通知」、複数の呼び出しを一度に行う「Batch」が可能。
  • リクエスト、レスポンスのjsonに含めるべきフィールドが決められており(プロトコルなので)、それを満たしさえすればよい。
  • HTTPメソッドは全てPOSTとするのが通例。

リクエス

以下、例は主にJSON-RPC 2.0 Specificationから拝借いたしました。

  • jsonrpc [string]: JSON-RPCのバージョン(現在2.0)
  • method [string]: 呼び出したいメソッド名
  • params [array|object]: メソッドの引数(単純に列挙する場合はarray、ラベルを使う場合はobject)
  • id [string|int]: リクエストを識別するID、レスポンスに同じ値が含まれる、よってBatch(後述)で送ってもどのリクエストに対するレスポンスかを識別できる
{
  "jsonrpc": "2.0",
  "method": "subtract",
  "params": [42, 23],
  "id": 1
}

ラベル付き

{
  "jsonrpc": "2.0",
  "method": "subtract",
  "params": {
    "subtrahend": 23,
    "minuend": 42
  },
  "id": 3
}

レスポンス

成功時:

  • jsonrpc [string]: JSON-RPCのバージョン
  • result [object]: 成功時のデータ、特にフォーマットの指定はない
  • id [string|int]: リクエストID

失敗時:

  • jsonrpc [string]: JSON-RPCのバージョン
  • error [object]: 失敗時のデータ、フォーマットは以下の通り
  • id [string|int]: リクエストID

errorのフォーマット

  • code [int]: エラーコード、あらかじめ定義されている → error object
  • message [string]: エラーメッセージ
  • data [any]: 追加情報用のフィールド、型の指定もなく、省略も可能

成功時:

{
  "jsonrpc": "2.0",
  "result": 19,
  "id": 1
}

失敗時:

{
  "jsonrpc": "2.0",
  "error": {
    "code": -32601,
    "message": "Method not found"
  },
  "id": "1"
}

通知

リクエスト時にIDフィールドを省略すると、レスポンスを期待しないと解釈され、何も返ってこない。これを「通知」と呼んでいる。

{
  "jsonrpc": "2.0",
  "method": "update",
  "params": [1,2,3,4,5]
}

Batch

トップレベルを配列にし、リクエストを複数一気に送ることができる。

リクエスト:

[
  {"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"}
]

GoでJSON-RPCを扱う代表的なパッケージは以下の3つ

【思ったより手間取っているので追記予定】

疑問

  • JSON-RPCを使う理由
    • URL設計が鍵になるRestAPIとメソッド設計が鍵になるJSON-RPCだと大分性格が違うと感じたが、どのケースはRestAPI向きでどのケースはJSON-RPC向きなのか
  • 一般的なidの割り振り方

参考


  1. RPCの例 wiki