Datawindowと厚切りJSON(後編)
What’s up, Japanese people?
どうも早速このキャラに飽きてきている裏切りエイタです。
前回は ImportJSON を利用してデータウィンドウに JSON を取り込む方法について説明しました。インポートとくれば当然、つぎはエクスポートですよね。
JSON でのエクスポートは ExportJSON メソッドで行います。このメソッドはデータウィンドウのデータを JSON 形式の文字列として返すのですが、構文によって必要なデータを出力対象にすることができます。
ところが、なんと ExportJSON には4つの構文があるんです・・・。
4つの構文
ExportJSON の4つの構文は、「1: Primaryバッファのみを出力」、「2: バッファを指定可」「3: バッファを複数指定可」、「4: バッファ、行、カラムを指定可」といった具合に出力するデータを指定する方法の違いがあるんですが・・・。
ともかく、詳しく見ていきましょう!
[構文 1] ~Primaryバッファのみ出力~
string dwcontrol.ExportJson( {boolean format} )
ひとつめの構文はかなりシンプル。オプションである Boolean 型の引数は、前回の ImportJSON で説明した「Simple JSON (false)」と「Standard Datawindow JSON (true)」の 2 つのフォーマットを選択することができます。 デフォルトは false の「Simple JSON」です。この引数はすべての構文に共通で含まれています。
出力する対象は Primary バッファの行のみ。 つまり画面上に見えてるデータですね。削除、フィルターされた行はこの構文では出力できません。
なお、他の 3 つの構文にも言えることですが、ExportJSON メソッドは「コンポジット」、「クロスタブ」、「OLE 2.0」、「リッチテキスト」のデータウィンドウ様式には対応していないのでご注意を。
[構文 2] ~バッファ指定、変更行のみ出力可~
string dwcontrol.ExportJson( {DWBuffer dwbuffer,} boolean changedonly, boolean format )
この構文ではオプションでバッファの指定ができます。削除された行のみ (Delete バッファ) とかね。さらに特徴的なのが第 2 引数。 true を渡すことで「変更された行」のみを出力することができるんです。
「変更された行」の定義がマニュアルに記載されていなかったので実際に動かして確認してみたところ、この引数が true の場合は行のステータスが DataModified! または NewModified! のデータが出力されるようです。 これは Update メソッドによる DB の更新や追加の対象と同じ行ですね。 これは便利そう!
[構文 3] ~バッファ複数指定、DatawindowChildデータ出力可~
string dwcontrol.ExportJson( boolean primarydata, boolean filterdata, boolean deletedata, boolean dwcdata {, boolean format} )
3 つめの構文は出力するバッファを複数指定することができます。ほかの構文では指定できるバッファは 1 つのみですが、この構文では「Delete バッファと Filter バッファのデータを出力!」なんてことができます。
さらに、DatawindowChild 内のデータを出力に含めることもできますよ。
[構文 4] ~バッファ指定、行/カラムの範囲指定可~
string dwcontrol.ExportJson( DWBuffer dwbuffer {, long startrow {, long endrow {, long startcolumn {, long endcolumn } } } } {, boolean format } )
最後の構文では行やカラムの範囲指定ができます。「5 ~ 10 行目、カラムID 3 ~ 6」というように、必要な行やカラムのみを出力できます! ただし、範囲による指定となるので行やカラムが連続していなければならず、出力したい行が飛び飛びの場合なんかは工夫が必要ですね。
いかがでしょうか? こうやって見ると構文それぞれで随分特徴がありますよね。 「あちらを立てればこちらが立たず」といった感もありますが、一般的な用途では大きな不都合はなさそうです。 「特定の範囲から変更された行のみ」みたいなケースでは、ステータスでフィルターをかけるといった具合に自力で絞り込むしかないようですね。
さて、今回も実際に使っていきましょう!
実践!
今回もサンプルプログラムを作ってみました。 データウィンドウは PowerBuilder 2017 R3 をインストールした際に一緒に入るデモ DB を利用して作成しています。 画面はこんな感じ↓
ボタンに処理を書きます。 まずは構文 2 で実践してみます。
cb_1 Clicked イベント
string ls_json ls_json = dw_1.ExportJson(Primary!, true, rb_2.checked) mle_1.text = ls_json
第 2 引数に true (変更した行のみ) を指定したので、データを一部変更して出力対象にします。
出力結果はこうなりました(整形してます)。
[ { "emp_id": 102, "emp_fname": "Fran", "emp_lname": "Whitney", "dept_id": 800, "city": "Needham", "birth_date": "1966-06-05" }, { "emp_id": 160, "emp_fname": "Robert", "emp_lname": "Breault", "dept_id": 100, "city": "Boston", "birth_date": "1955-05-13" } ]
変更した 2 行だけが出力されていますね。 ちなみに Standard Datawindow JSON 形式で出力すると・・・。
{ "identity": "70c86603-983b-4bd9-adbc-259436e43cbd", "version": 1, "platform": "PowerBuilder", "mapping-method": 0, "dataobject": { "name": "d_employee", "meta-columns": [ { "name": "emp_id", "index": 0, "datatype": "long", "nullable": 1 }, { "name": "emp_fname", "index": 1, "datatype": "string", "nullable": 1 }, { "name": "emp_lname", "index": 2, "datatype": "string", "nullable": 1 }, { "name": "dept_id", "index": 3, "datatype": "long", "nullable": 1 }, { "name": "city", "index": 4, "datatype": "string", "nullable": 1 }, { "name": "birth_date", "index": 5, "datatype": "date", "nullable": 1 } ], "primary-rows": [ { "row-status": 1, "columns": { "emp_id": [102], "emp_fname": ["Fran"], "emp_lname": ["Whitney"], "dept_id": [800, 1, 100], "city": ["Needham"], "birth_date": ["1966-06-05"] } }, { "row-status": 1, "columns": { "emp_id": [160], "emp_fname": ["Robert"], "emp_lname": ["Breault"], "dept_id": [100], "city": ["Boston", 1, "Milton"], "birth_date": ["1955-05-13"] } } ] } }
ご覧の通り、各カラムの情報やバッファ情報が付加されています。 さらによく見ると、
"city": ["Boston", 1, "Milton"]
といったように変更前の値も保持されていますね!
もともとデータウィンドウは検索した時点の値も保持しており、値が変更された後でも元の値を取得できるようになっています。 そういった情報も JSON データとして出力することで別システムに渡すことができるというわけです。 このようなことは、これまでのバージョンでは GetFullState メソッドでデータウィンドウを丸ごと (データだけでなくコントロールの位置や色まで全部!) を「バイナリ形式」で出力することができましたが、ExportJSON ではデータにかかわる情報のみを文字列で出力できるようになったので用途の幅が広がりそうです。
Next!
お次は構文 3 を使って DatawindowChild のデータも出力してみましょう!
cb_2 Clicked イベント
string ls_json dw_1.SetFilter("birth_date >= date('1970/01/01')") dw_1.Filter() ls_json = dw_1.ExportJson(true, false, false, true, rb_2.checked) mle_1.text = ls_json
出力対象は Primary:〇、Filter:×、Delete:×、そして DatawindowChild データの出力を指定しています。 また、データが多くなるので出力前に誕生日 (birth_date) でフィルターをかけています。
[ { "emp_id": 129, "emp_fname": "Philip", "emp_lname": "Chin", "dept_id": 600, "city": "Atlanta", "birth_date": "1974-10-30" }, { "emp_id": 191, "emp_fname": "红红", "emp_lname": "王", "dept_id": 700, "city": "北京", "birth_date": "1972-12-21" }, { "emp_id": 195, "emp_fname": "慧敏", "emp_lname": "劉", "dept_id": 800, "city": "上海", "birth_date": "1971-07-19" }, { "emp_id": 207, "emp_fname": "杰明", "emp_lname": "李", "dept_id": 600, "city": "北京", "birth_date": "1979-09-12" }, { "emp_id": 278, "emp_fname": "Terry", "emp_lname": "Melkisetian", "dept_id": 100, "city": "Watertown", "birth_date": "1974-05-17" }, { "emp_id": 299, "emp_fname": "Rollin", "emp_lname": "Overbey", "dept_id": 200, "city": "Emeryville", "birth_date": "1972-03-15" }, { "dept_id": 100, "dept_name": "R & D" }, { "dept_id": 200, "dept_name": "판매부" }, { "dept_id": 300, "dept_name": "财务部" }, { "dept_id": 400, "dept_name": "市場部" }, { "dept_id": 500, "dept_name": "Service Commercial" }, { "dept_id": 600, "dept_name": "Ventas" }, { "dept_id": 700, "dept_name": "Personalabteilung" }, { "dept_id": 800, "dept_name": "カスタマー サポート" } ]
DatawindowChild のデータは・・・というと、各行のデータの後に続いて同じレベルで追加されています。Standard~ 形式では出力結果がとても長くなるので割愛しますが、”dwchilds” というオブジェクトに格納されます (前編の「フォーマット」を参照)。
ImportJSON と同じように、簡単に出力することができました!
まとめ
JSON のインポートに続いてエクスポートをご紹介しましたが、どちらもたった 1 行のコードで実現できるというのは、生産性や保守性の点から見ても大きなメリットだと感じました。同時に PowerBuilder 2017 R2 から追加された RestClient や HTTPClient を駆使することで Web API とのデータ連携もスムーズに行うことができます。
JSON は RESTful Web API をはじめとして、データ交換におけるデファクトスタンダードになっています。その JSON を取り扱えるようになったことは、クラサバだけにとどまらない、PowerBuilder が持つ大きなポテンシャルを 象徴 しているかのようです。
・・・・・。
Why Japanese people!?
「象徴」ってどういうこと? 「象」って Elephant のことでしょ! ゾウの特徴?? 長い鼻かよ!
・・・以上!!!!