この記事は、JSON-RPC 2.0 を調べたことを走り書きしたレベルものです。実際の利用経験に基づいた情報でもなければ、しっかり時間をかけて裏付けをとった情報でもないため、誤った理解が含まれている可能性がある点にご注意ください。ツッコミや編集リクエストは歓迎します。

概要

JSON-RPC は、 RPC (Remote Procedure Call) を実現するプロトコルの1つです。その名の通りJSON形式でリクエスト&レスポンスを表現するシンプルな仕様となっています。

例えば、次のようなリクエストをJSONで送ると、別のマシンで subtract(42, 23) が実行され、結果の 19 がレスポンスとして返ってきます。

request
{"jsonrpc": "2.0", "method": "subtract", "params": [42, 23], "id": 1}
response
{"jsonrpc": "2.0", "result": 19, "id": 1}

プロトコルの仕様でしかないため、どう実現されるかは個別の実装に委ねられる点に注意してください。

JSONを使ったシンプルなやりとりになるため、Webブラウザやモバイルアプリなどのクライアントからサーバーへ通信するときだけでなく、マイクロサービスにおけるサーバー間の通信にも利用できます。

サンプル

基本形

典型的なパターンは次の通りです。

request
{"jsonrpc": "2.0", "method": "subtract", "params": [42, 23], "id": 1}
response
{"jsonrpc": "2.0", "result": 19, "id": 1}
  • jsonrpc はバージョン1.0と区別するためのフィールドで 2.0 固定
  • method は実行する関数名
  • params は関数の引数リスト
  • id はリクエストを識別する番号(レスポンスに同じ番号が入るので追跡できる)
  • result は実行結果が入る任意のオブジェクト

名前付き引数

関数のパラメーターは、名前付き引数で指定することもできます。

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

通知 (Notification)

id フィールドを省略すると通知とみなされます。この場合は、サーバーからレスポンスは返ってきません。

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

エラー

エラーが発生した場合は、 result の代わりに error オブジェクトが返却されます。エラーコード code は -32768 〜 -32000 があらかじめ予約されていてかなり違和感がありますが、 XML-RPC にならっているとのことです。

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

バッチ (Batch)

複数のリクエストをまとめて送ることもできます。レスポンスのリストは順番が保証されていないため、 id フィールドを使ってリクエストと突き合わせる必要があります。

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

Java

メリット?

  • REST APIよりはURL設計が楽そう
    • エンドポイントとなるURLは1つでもよい(リクエストの中身で method を指定するので)
    • 同じリソースに複数操作がある場合などに表現しやすいはず
  • ただのJSONなのでクライアント/サーバー間の通信でも使える
  • Batchリクエストの機能は便利そう
  • 通信レイヤーはHTTPに限定されないので、WebSocketなどと組み合わせても使える

デメリット?

  • REST APIほどは周辺のエコシステム(デバッグツールやAPIドキュメント生成など)が揃っていなさそう
  • リクエストの中身を見ないとどんな操作を要求するリクエストか分からずデバッグしづらそう
  • すべてPOSTで id も毎回変わるとなるとキャッシュを効かせづらそう

調査できていない

  • APIドキュメント系のツール
  • プログラム自動生成系のツール(アプリケーションのひな形やテストコード)

参考情報

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.