Finally, the year is just a few days away.
I recently wrote an article about converting IBMi data to JSON with Magic xpi for use in DominoLeap.
This time, I report that the data is now available in Notes client using Lotusscript.
There were a few things to note in the JSON specification, which I hope will be helpful.
みなさま、こんにちは。
いよいよ今年もあとわずかですね。
早速ですが、先日
#Magic #xpi を介した #DominoVolt ( #DominoLeap ) と #IBMi の連携
という記事で、IBMiにあるデータをMagic xpiを経由することでJSON化して、DominoVolt(DominoLeap)に取得するという内容を紹介しました。
もちろん弊社にとって、要求された内容ではあったのですが、現状ノーツクライアントに依存している環境から、LeapでなくNotes側でも利用したいということは言うまでもありません。
ノーツクライアントでのREST APIについては、
#郵便番号 から #住所 を取得しよう( #鬼わか の #REST #API を適用したサンプル)
こちらの記事で、提供されたサンプルを紹介しましたので、こちらに割り当てていくことで簡単にできるのではと安易に考えていたのです。
ということで、いざ!!
とまずは鬼わかで利用したフォームごとコピーしてきてテストを開始しました。
私はLotusscriptをほとんど使用していない、未熟者になります。
そんな私が、鬼わかのコードを読んでいくと、いろいろと丁寧な処理が含まれていることに気づきました。
私なりにその「丁寧な部分」を外していき、シンプルな構成にしていけるだろうと実行してみたのですが結果はNG。
NotesJSONNavigatorにセットしたいのですが、以下エラーが発生しました。
「JSON 文字列を解析できません: Invalid value. offset 0」
デバッガーで見てもわからず、今回もまたサポートの方の手を煩わせることになってしまいました。
まず指摘があったのが、「レスポンスはバイト配列にはなっていない」との事でした。
そこでChromeの開発者ツールを使用して情報提供の依頼があり、対応しました。
ちなみにこの部分については、以下記事を紹介頂きました。
https://support.hcltechsw.com/csm?id=kb_article&sysparm_article=KB0039010
指示されたデータを提出すると、「レスポンスヘッダが、「Content-Type: text/html」となっている」との指摘がありました。
レスポンスヘッダの「Content-Type」に「application/json」をセットしてくださいとの指示を頂きました。
こちらはMagic側の問題と考え、マジックソフト社のサポートへ連絡して指示を仰ぎました。
そもそもJSONとしてデータを取得しているので、デフォルトでそうなっていないのが少し疑問・・・といいますか、先のDominoLeapは解釈してくれてたんだぁ・・・と違和感の残る結果ではありますが、無事サポートの指示により「Content-Type=pplication/json」をセットすることができました。
その後、再度実行したのですが、今度は以下エラーが表示されました。
「HTTP 応答コンテンツタイプはサポートされません」
上記を報告したところ、テスト用のスクリプトを提供頂き、試すこととなりました。
ここで私のミス1回目
Magic xpi ですが、開発用のサーバーでテストを行っております。
開発用の制限として、プロジェクトは24時間で自動終了するという仕様があることを忘れておりました。
つまり・・・「応答なし」状態で問い合わせを継続していたということです。
・・・申し訳ありません・・・
再度テストを行う際に、Wireshark を使ってネットワークキャプチャしたデータの提供ができないかとの相談がありました。
現時点で私のクライアントにインストールしたV12.0.2(64bit)でテストしていたため、こちらも問題なく対応し、データを提供したところ。
「Content-Type:」 と「application/json」の間に半角スペースが2つあります
との事。
あわててMagicの設定を見ると、確かにスペースが入っています。
私がどこかでコピペしたのですが、そもそもそちらに入っていたようです。
またヘッダ部分とBody部分の間に不要な文字が含まれていることも判明しました。
この文字列については再度マジック社に問い合わせたところ、BOM付きのデータになっているとの事でした。
この時点でBOMは外せなかったので、そのままテストし、Wiresharkのデータを解析して頂きました。
しかしながらやはり、BOMが邪魔のようで、Lotusscript側で外すスクリプトの提供を頂きました。
' BOM 除去 i=0 ReDim json(UBound(returnValue)-3) ForAll x In returnValue If i > 2 Then json(i-3) = x End If i = i + 1 End ForAll |
何度も申し訳ございません orz お恥ずかしい限りで・・・
Sub Initialize Dim ws As New NotesUIWorkspace Dim uidoc As NotesUIDocument Dim session As New NotesSession Dim http As NotesHTTPRequest Dim url As String Dim returnValue As Variant Dim i As Integer Dim json As string Set uidoc = ws.CurrentDocument url = "URLを指定する" Set http = session.CreateHTTPRequest() Call http.SetHeaderField("Accept", "application/json") http.Preferstrings=true returnValue = http.Get(url) json = Mid(returnValue,2,Len(returnValue)) Dim jsonNav As NotesJSONNavigator Dim jsonElement As NotesJSONElement Set jsonNav = session.CreateJSONNavigator(json) Set jsonElement = jsonNav.Getelementbyname("JSONのKEY") msgbox "value=" + jsonElement.Value + " type=" + CStr(jsonElement.type) End Sub |
こちらを実行すると、想定されたメッセージボックスが表示されました!!
ここまでくれば、あとはJSONのデータを必要なフィールドに割当てるだけ。
Sub Click(Source As Button) Dim ws As New NotesUIWorkspace Dim uidoc As NotesUIDocument Dim session As New NotesSession Dim http As NotesHTTPRequest Dim url As String Dim returnValue As Variant Dim textCode As String Dim json As String ' "zip"フィールドの値を取得して、リクエストURIを生成 Set uidoc = ws.CurrentDocument textCode = uidoc.FieldGetText("zip") url = "REST接続するURLを記述" url = url + textCode ' Getリクエストを実行し、結果を取得 Set http = session.CreateHTTPRequest() Call http.SetHeaderField("Accept", "application/json") http.Preferstrings=True returnValue = http.Get(url) json = Mid(returnValue,2,Len(returnValue)) 'JSON パース Dim jsonNav As NotesJSONNavigator Dim jsonElement1 As NotesJSONElement Dim jsonElement2 As NotesJSONElement Dim jsonElement3 As NotesJSONElement ' JSON データを JsonNevigator 型にデータにセットする Set jsonNav = session.CreateJSONNavigator(json) Set jsonElement1 = jsonNav.Getelementbyname("JSONの値1") Set jsonElement2 = jsonNav.Getelementbyname("JSONの値2") Set jsonElement3 = jsonNav.Getelementbyname("JSONの値3") Call uidoc.FieldSetText("address", jsonElement1.Value) Call uidoc.FieldSetText("address_1", jsonElement2.Value) Call uidoc.FieldSetText("address_2", jsonElement3.Value) Call uidoc.Refresh() End Sub |
以上で指定した値をそれぞれ準備したaddressフィールドにセットすることができました。
ちなみに今回サポートの方とのやり取りは、約2週間。38回にもわたりました。
・・・本当に申し訳ございません。
ただおかげ様で、やりたかった事が無事実現できました。
ので、正月休みに作業します(汗
長くなりましたが、LotusscriptでJSONを扱い場合、今回の経験で判明した内容です。
-----まとめ-----
- JSONのレスポンスはバイト配列の必要がある
- レスポンスヘッダの「Content-Type」は「application/json」であること
- 文字コードはUTF-8であること
- (現時点で)BOM付きはエラーになるため、外すこと
皆様もお気をつけください!!