そんな時、あるよねぇ~。と昔の海外通販の謎ドラマみたいな書き出しは置いておいて、、、ColdFusionに限らずWebアプリではそのサーバー単体で完結するのではなく、別に動いているWebシステムなどと連携してデータをやり取りするような事がしばしば起こると思う。
リモートのWebシステムとやり取りするのにとても便利なのが、cfhttp。これはColdFusion内部の仮想ブラウザ機能から指定したURLにHTTPアクセスをして、結果をColdFusionで受け取ることができる。
cfhttpにはcfhttpparamというサブタグがあって、cookieや、POST時のFormパラメータ、ヘッダやファイルを送信することができる。 今回は、POSTでJSONデータを送りたい場合についての備忘録を書いておく。といっても、今回も先人の知恵を借りるってパターン。
stackoverflowに投稿された質問に対する回答(最初の回答:一番有用だったもの)にそのものズバリの回答が載っている。
■タグで記述 <cfset stFields = { "fields" = { "first_name" = "myFirstName" }, "email" = "email@domain.com" }> <cfhttp url="http://api.url.com" method="post" result="httpResp" timeout="60"> <cfhttpparam type="header" name="Content-Type" value="application/json" /> <cfhttpparam type="body" value="#SerializeJSON(stFields)#"> </cfhttp> ■関数で記述 <cfscript> stFields = { "fields" = { "first_name" = "myFirstName" }, "email" = "email@domain.com" } cfhttp(method="post", url="https://www.google.com/", result="httpResp", timeout="60") { cfhttpparam(type="header", name="Content-Type", value="application/json"); cfhttpparam(type="body", value="#SerializeJSON(stFields)#"); } writeDump(httpResp); </cfscript>
ColdFusionは構造体データをJSONに変換するSerializeJSON関数があるのでそれを使用すると簡単にJSONデータを作れる。 そのデータを、cfhttpparamのtype="header"でContent-Typeをapplication/jsonを指定して、type="body"で渡す。 実行すると、呼び出した結果がhttpResp.FileContentに戻される。
他にもStatusCodeやResponseheaderなどの情報も戻されるので、cfhttpを実行するときは、cfdumpで確認してみることがお勧め(
<cfdump var="#httpResp#">
)。もし、cfhttpにresult属性を追加しなかった場合は、自動的にcfhttp構造体が作成され、そこに結果が戻されている(#cfhttp.FileContent#)。
その他のポイント
もし、JSONデータを渡す際に”項目の順番”が決まっているような場合(あるのか?)は、ColdFusion 2016以降で可能になった構造体の順序を維持する設定を行うと良い。stFields内の入れ子となっているfieldsの項目を順番を維持して指定する場合は、{ を [ に変えると良い({}が通常の構造体(順番は任意)、[]が順序を維持する構造体)
<cfset stFields = { "fields" = [ "first_name" = "myFirstName", "last_name": "myLastName", "sub1": 0, "sub2": true, "sub3": "string" ], "email" = "email@domain.com" }>
もし、日本語が文字化けをする場合などは、Content-Type の値(application/json)にcharsetを付ける
<cfhttpparam type="header" name="Content-Type" value="application/json; charset=UTF-8" >
もしくは、日本語を事前にURLEncodedFormat・EncodeForURL関数を使用してURLエンコードするなどもある