mursのColdFusionメモ

頭の中から抜け落ちていく情報をメモがわりに書き溜めていくブログです。

ColdFusionからリモートのAPIにJSONデータを送り付けたい

そんな時、あるよねぇ~。と昔の海外通販の謎ドラマみたいな書き出しは置いておいて、、、ColdFusionに限らずWebアプリではそのサーバー単体で完結するのではなく、別に動いているWebシステムなどと連携してデータをやり取りするような事がしばしば起こると思う。

リモートのWebシステムとやり取りするのにとても便利なのが、cfhttp。これはColdFusion内部の仮想ブラウザ機能から指定したURLにHTTPアクセスをして、結果をColdFusionで受け取ることができる。

helpx.adobe.com

cfhttpにはcfhttpparamというサブタグがあって、cookieや、POST時のFormパラメータ、ヘッダやファイルを送信することができる。 今回は、POSTでJSONデータを送りたい場合についての備忘録を書いておく。といっても、今回も先人の知恵を借りるってパターン。

stackoverflow.com

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エンコードするなどもある