How to POST JSON Data to Remote API Using Coldfusion CFHTTP

goxmedia picture goxmedia · Jan 19, 2012 · Viewed 32.5k times · Source

I'm sure that I'm completely botching this up but I got this far with the help of fellow Stack Overflow users, so thanks thus far.

I need to POST JSON data to a remote API. Obviously I can't use jQuery due to SOP issues, and the remote API does not support JSONP.

I also don't want to have to use any type of proxy as to get around the SOP limitations.

Per the API docs (http://myemma.com/api-docs/), this is the formatting of the data they expect (request and response data is transferred as JSON):

POST https://api.e2ma.net//123/members/add
{
  "fields": {
    "first_name": "myFirstName"
  }, 
  "email": "[email protected]"
}

And this is what I've built thus far but continue to receive "unable to parse JSON" errors from the remote API:

<cfset fields[name_first]="#SerializeJSON( "myFirstName" )#" />
<cfset form.email="#SerializeJSON( "[email protected]" )#" />

<cfhttp
  url="https://api.e2ma.net/123/members/add"
  method="POST"
  username="username"
  password="pssword"
  useragent="#CGI.http_user_agent#"
  result="objGet">

  <!--- add email --->
  <cfhttpparam
    type="formfield"
    name="email"
    value='#form.email#'
  />

  <!--- add field: name_first --->
  <cfhttpparam
    type="formfield"
    name="fields"
    value='#fields[name_first]#'
  />

</cfhttp>

<cfoutput>#objGet.FileContent#</cfoutput>

Again, I'm surely mangling the structure of my data somehow, but I'm not sure what I'm doing wrong, particularly regarding properly setting the "fields": { "first_name": "myFirstName" } structure/array.

Answer

timbrown picture timbrown · Feb 4, 2012

You should send your request string as the httpparam type of body. The body of the request could be something like the entire form scope of your prepped structure. Be sure to either use array notation for setting your structure keys or put them in "quotes" during the implicit structure creation to ensure they retain their proper casing when the serializeJSON() takes place otherwise ColdFusion will uppercase the structure keys.

<cfset stFields = {
    "fields" = {
        "first_name" = "myFirstName"
     }, 
     "email" = "[email protected]"
}>   

<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>

Update 10/26/13
For all the work I've been doing lately with APIs I thought I'd update an easy way to automate this casing that I've found. I've used a combination of the JSON Util library and Ben Nadel's JSON Serializer Utility CFC to accomplish much better serialization consistency for all returns.

Below is an example GIST of how I've implemented this.
https://gist.github.com/timmaybrown/7226809

As I've transitioned to using persistent entity CFCs in my projects, I've found that extending Ben Nadel's serializer CFC with my own child CFC method that loops all my persistent cfc's properties using the getComponentMetaData() function to build a structure of distinct keys and the casing for the serialization to follow. The approach allows my api to inherit automatically the casing of my property names within my entities and is very useful. A bit of overhead on reinit, but well worth it to keep your casing consistent in your API.

Update 9/8/16 Re: my point above about consistent casing. I have trended toward a different column naming convention in my databases for newer projects so I don't have to fight with a lot of these issues. first_name instead of firstName etc.