JSON-RPC v1.0は2005年に登場し、5年後に2番目のバージョンが登場しました 。 JavaScriptおよびモバイルアプリケーションの時代において、多くの開発者は、既成のシンプルな標準ではなく、独自のバイクを使用しています。
なぜJSON-RPC、さらには2.0なのか?
主な機能を強調してみます。
- 少なくともいくつかの標準です。 さまざまなプラットフォーム用の幅広いライブラリ。
- 高速で簡単な解析。 JSON-RPCはXML-RPCやSOAPほど巨大ではありません。
- 組み込みのエラー処理。 RESTバイクでは、答えを作成する方法と次に何をすべきかを把握する必要があります。
- コールキューのサポート。 これで、5つのHTTP要求を1つにラップできます:)。
- APIの単一ポイント。 たとえば、/ rpc-server.phpはさまざまなメソッドを処理できます。
- メソッドを呼び出すときの名前付きおよびオプションのパラメーターのサポート。
バージョン1.0に精通している人にとって、2.0の重要な革新はパラメーターとコールキューと呼ばれていました。
簡単なリクエスト/レスポンスは次のとおりです。
--> {"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": [42, 23], "id": 1} <-- {"jsonrpc": "2.0", "result": 19, "id": 1} --> [ {"jsonrpc": "2.0", "method": "sum", "params": [1,2,4], "id": "1"}, {"jsonrpc": "2.0", "method": "foobar", "id": "2"} ] <-- [ {"jsonrpc": "2.0", "result": 7, "id": "1"}, {"jsonrpc": "2.0", "error": {"code": -32601, "message": "Method not found."}, "id": "2"} ]
プログラミングのこの複雑な「創造的な」世界では、疑問が常に生じます。準備ができているのか、自分の何かを書くのか?
完璧な世界。 何が必要ですか?
通常どおり、検索/取得するツールの基準を定義します。
- 仕様への完全準拠。 この要因を考えると、他のクライアント/サーバーソリューションで問題が発生する可能性はほとんどありません。
- 単一ファイルに依存しない実装。 フレームワークをZendやPEARにドラッグしたくない
- テストの可用性。 少なくとも、オープンソースソリューションが正しく機能することを保証します;)
- 内部の美しい実装 。 すべてが可能な限りシンプルで明確かつ論理的でなければなりません。
- 自動検出メカニズムの存在。 JSON-RPCサーバーは、そのメソッドに関するメタ情報を提供できる必要があります
- 簡単な接続。 いくつかのメソッドと呼ばれるファイルを接続しましたが、すべて機能します。
- クライアントプロキシクラスの生成。 メタデータを備えた既製のサーバーが既にあるのに、なぜクライアントを作成するのですか? ;)
開始するには十分です。
理論のビット
なぜなら JSON-RPCはかなり新しいプロトコルですが、まだ完全には承認されていない瞬間があります。 それらの1つは、Dojoによって提案されたサービスマッピング記述です。 SMDは、メソッドから始めて、デプロイされた戻り値型で終わるWebサービスを完全に記述することができます。 残念ながら、 Zend_Json_Server 、inputExフレームワーク( テストフォームの生成 )、 Dojoフレームワークなど、実装をサポートするソリューションはほとんどありません。
既存のソリューションの検索に移りましょう。
PHPの既存の実装
ウィキペディアのタブレットからクライアントのリストを取得しました。
php-json-rpc | jsonrpc2php | チボカ | ジュニア | json-rpc-php | JSONRpc2 | ゼンド
ジョンソン サーバー | zoServices | |
サーバー | ||||||||
コンプライアンス | - | バッチモードでの通知の正しいサポート。
| + | オプションの名前付きパラメーターはありません | + | + | + | オプションの名前付きパラメーターはありません |
ファイル数 | - | 2 | > 7 | 3 | 6 | 1 | > 5 | 6 |
SMD回路 | - | - | - | - | - | - | + | - |
テスト | - | + | - | + | - | + | + | - |
内部実装(1..5) | - | 4
エクスポートされた関数の手動マッピング | 3.このような単純なタスクには実装が複雑すぎる | 4 | 4.難しい | 4.マジックインサイド! | 4+。 ゼンド | 3。 |
お客様 | ||||||||
コンプライアンス | バッチと通知なし | - | + | + | + | バッチなし | - | 通知がありません |
ファイル数 | 1 | - | > 7 | 4 | 2 | 1 | - | 6 |
テスト | - | - | - | + | - | + | - | - |
内部実装(1..5) | 4 | - | 3.メソッドを呼び出すための追加手順 | 4 | 4 | 4+。 :) | - | 3 |
自動生成 | - | - | - | - | - | - | - | - |
スマートリーダーは、それがどのような違いを生み、実装に使用するファイルの数を主張するかもしれませんが、すべてを1つに接着することができます。 はい、できますが、これは追加の追加アクションです。
ご覧のとおり、私たちに合った、ファイルなしで安全に使用できる「理想的な」ソリューションはありません。 他のプラットフォームの方がずっといいと思います:)
一般的に未完成のプロジェクトがありますが、エクスポートされたAPI(サーバー、smd-schema、クライアント生成)を使用する完全なサイクルを提供できるソリューションはありません。
また、PHPを作成しようとしている開発者(JavaやC#など)を本当に理解していません。 ほとんどの場合、PHPは要求/応答スキームで使用され、状態を含むアプリケーションサーバースキームでは使用されません。 スクリプトは、コンパイルされたプライベートライブラリではありません。
「準備が整ったものを使用する」または「自分で作成する」という質問に対する答えは明らかです。
Eazy JSON-RPC 2.0
GitHubのプロジェクト。 前に示したすべての要件が実装されています:)
サーバー
2つのユースケースがあります:BaseJsonRpcServerクラスを継承するか、そのインスタンスを作成して、エクスポートされたオブジェクトをコンストラクターに渡します。
<?php include 'BaseJsonRpcServer.php'; include 'tests/lib/DateTimeRpcService.php'; // $server = new DateTimeRpcService(); // new BaseJsonRpcServer( new DateTimeService() ); $server->Execute();
したがって、DateTimeRpcServiceクラスのすべてのパブリックメソッドを公開しました。 SMDスキームは、 smd GETパラメーター(たとえば、 eazyjsonrpc / example-server.php?Smd )から取得できます。 スキームを構築するとき、phpDocブロックが考慮されます。
どんな回路があるのか......
{"transport":"POST","envelope":"JSON-RPC-2.0","SMDVersion":"2.0","contentType":"application\/json","target":"\/example-server.php","services":{"GetTime":{"parameters":[{"name":"timezone","optional":true,"type":"string","default":"UTC"},{"name":"format","optional":true,"type":"string","default":"c"}],"description":"Get Current Time","returns":{"type":"string"}},"GetTimeZones":{"parameters":[],"description":"Returns associative array containing dst, offset and the timezone name","returns":{"type":"array"}},"GetRelativeTime":{"parameters":[{"name":"text","optional":false,"type":"string","description":"a date\/time string\r"},{"name":"timezone","optional":true,"type":"string","default":"UTC"},{"name":"format","optional":true,"type":"string","default":"c"}],"description":"Get Relative time","returns":{"type":"string"}},"Implode":{"parameters":[{"name":"glue","optional":false,"type":"string"},{"name":"pieces","optional":true,"type":"array","default":["1","2","3"]}],"description":"Implode Function","returns":{"type":"string","description":"string"}}},"description":"Simple Date Time Service"}
クライアント
再び2つの用途が考えられます:BaseJsonRpcClientクラスのインスタンスを作成し、コンストラクターでWebサービスリンクを渡すか、ジェネレーターを使用します。
<?php include 'BaseJsonRpcClient.php'; $client = new BaseJsonRpcClient( 'http://eazyjsonrpc/example-server.php' ); $result = $client->GetRelativeTime( 'yesterday' );
発電機
SMDスキームに基づいて、サーバーを操作するためのクラスを生成できます( DateTimeServiceClient.phpの例を参照)。 これを行うには、ジェネレーターを呼び出します。
php JsonRpcClientGenerator.php http://eazyjsonrpc/example-server.php?smd DateTimeServiceClient
コマンドの結果は、必要なメソッドを含むDateTimeServiceClient.phpファイルになります。
軟膏で飛ぶ
JSON-RPCでclass- > method()を呼び出す暗黙のルールは、 class.methodをメソッドの名前として(ドットを使用して)使用しています。
現在の実装では、このような機能は提供されていません。 urlはエクスポートされたクラスであると想定されているため、点線のオプションは表示されなくなります:)。 クライアント側に関しては、ここにいつでも追加できます。これは単なるPHPです。
また、SMDでは、戻り値の型をプロパティとオブジェクトの形で記述することもできますが、実装の複雑さを考慮して、この瞬間は省略します。
詳細なドキュメントを探している人のために、メソッドの名前、それらへのphpDocコメント、およびサーバーまたはクライアントのソースコードを読むことをお勧めします。
ライフハック
認証には何がありますか?
いくつかの実装オプションがあります。
- HTTP基本認証を使用します。 クライアントでは、ユーザー名とパスワードを$ CurlOptions配列に追加するだけです:)
- HTTPヘッダーを介してトークンを使用します。 トークンを取得するには、必要なメソッドを記述できます。
- メソッドパラメータとしてトークンを使用します。
ファイルのアップロードはどうですか?
base64でファイルをエンコードし、それを何らかのフィールドに送信するという奇妙なオプションを提供する人もいます。
多かれ少なかれ通常の解決策は、ファイルのダウンロードを開始できるアドレスを通知するメソッドを実装することです。
例
--> {"jsonrpc": "2.0", "method": "send_image", "params": ..., "id": 1} <-- {"jsonrpc": "2.0", "result": {"URL": "/exampleurl?id=12345", "maxsize": 10000000, "accepted-format":["jpg", "png"]}, "id": 1} --> . , --> {"jsonrpc": "2.0", "method": "send_done", "params": {"checksum": "1a5e8f13"}, "id": 2} <-- {"jsonrpc": "2.0", "result": "ok"}
エラー処理
プロトコル自体は、 コード 、 メッセージ、およびデータフィールドを持つエラーオブジェクトの存在をすでに提供しています。 呼び出されたメソッド内でBaseJsonRpcServerを使用する場合、 コードとデータを渡す例外をスローできます 。 特定のコードを使用して、 メッセージを$ errorMessages配列に追加できます。
特定のフィールドのみを持つオブジェクトをエクスポートする
それはすべて完全にあなた次第ですが、どのように実装するかはそうなります。 オブジェクトの必要な配列への変換を実装するクラスObjectToJsonConverterを作成することのみをお勧めします。
例
<?php class ObjectToJsonConverter { /** * @param City $city * @return array */ public static function GetCity( City $city ) { return array( 'id' => $city->cityId , 'name' => $city->title , 'region' => $city->region->title ); } } // - return array_map( 'ObjectToJsonConverter::GetCity', $cities );
クライアント側オブジェクトに変換
繰り返しますが、それはすべてあなた次第です。 たとえば、必要なクラスを作成し、簡単なコンバーターを書き戻すことができます(変換のアイデアはMyShowsClient.phpで取得できます)
おわりに
記事を読んだ後、インタラクションプロトコルを選択するときにJSON-RPCが注意を奪われないことを願っています。
> 89%のコードのテストをカバーした後でも、「うまくいくようだ」としか言えません:)