BASE64 and JSON

I have been working on a project that requires me to make an AJAX request to a ColdFusion service that returns a BASE64 version of an image wrapped in JSON. This JSON packet is used by the client-side to populate the SRC argument of an <IMG> tag. The process was working fine most of the time. But, every once and a while the image is broken.

After doing some checking I noticed that on the client-side the BASE64 string was not the same as the server-side.  The issue was that parts of the string were being transposed. It seems that the browser(s) were thinking that parts of the string were Unicode because some images strings contained sub-strings of u+a4f7 or u+c19b.

To correct the transposing issue ended up adjusting the client-side code and the ColdFusion service. First, on the server-side I wrapped the BASE64 process in the URLEndcodedFormat()function. Second, I adjusted the client-side code to decodeURI() the string from the JSON packet.

This process resolved the issue.

JSON data wrapping

While working with a development team on a RESTful solution I start proposing wrapping the service response/output in another object. This would allow us to write some META data about the response.

This META data would help developers with understanding what was going on with their request and the response provided by the service. A kinda talk back method to AJAX or REST responses.

A lot of people would say why would you need this? Well maybe you have a service that is open to the public like Twitter. You want developers to be able to access your service and understand your data without them calling or emailing you all the time. Maybe your information is labelled or structured differently than theirs. The META data provided in the wrapper would allow them to determine how to interpret the information to suit their needs.

Wrapper structure sample:


{
  "statusCode" : 1000,
  "requestID" : "63D62A09-AA1F-88CF-E890EDBF000F4F8E",
  "data" = {
    "message" : "Success", 
    "totalRows" : 1, 
    "columns" : {}, 
	"results" : []
  },
  "eventName" : "",
  "requestParams" : {}
}

Elements/Attributes of the wrapper

Path Notes
statusCode This status code is used to denote what is going on with the service or method being accessed.It is different from that of the Header status or AJAX request status.

These values can be set to reflect your status indicators.

requestID The requestID is optional and has many possible uses.First, it can be used to let developers know that the response is not cached.

Second, if you are keeping a log of requests for security, debugging, or user statistics this value will come in handy. Developers could submit a bug with the JSON packet that they received. This could help you debug possible issues with the data they supplied the service.

data This is where we would store data that the developer might want to display to end-users.
data.message The message field allows the service to send text or human messages back to end-user or developer. This message can be related to the numeric status indicator or independent.For example, say that the developer was making a request to log in. The statusCode could be 5000 letting the developer know that the method is working correctly. But, the was an error. The message element would hold the server response Password is not correct.

These messages can be handing in notifying the user of bad/missing parameters or with debugging of where the service broke.

data.totalRows This is an optional element. It is here to help the developer display the number of records being returned.
data.colmuns This is a optional element. I sometimes use it to display the column names of the query and denote if the column is a string, integer, boolean, array, UUID, GUID, or date.This helps the developer know you are returning 1 or 0 for a boolean response. And not for a number count.
data.results This is where you would normally store all the data that would be displayed to the end user.
eventName This element is used to help the developer verify that the are accessing the right method.

I normally user the path to the service. /com/members/readMembers/

requestParams This array would list all of the parameters that were sent as part of the request. This helps the developer debug responses.

Full structure sample


{
  "statusCode" : 1000,
  "requestID" : "63D62A09-AA1F-88CF-E890EDBF000F4F8E",
  "data" = {
    "message" : "Success", 
    "totalRows" : 3, 
    "columns" : {
      "productID" : "UUID", 
      "title" : "string", 
      "price" : "integer", 
      "availableUnits" : "integer"
    }, 
    "results" : [
      {
        "productID" : "502AD47D-05C6-4A47-9DD11458B8211EEB", 
        "title" : "Dell Inspiron 15 15.6\" Laptop Computer - Black", 
        "price" : 229.99, 
        "availableUnits" : 24
      },
      {
        "productID" : "93E84FE4-5367-4DD3-87F15C6A862ADA11", 
        "title" : "AOC e2252Swdn 22\" LED Monitor", 
        "price" : 99.99, 
        "availableUnits" : 102
      },
      {
        "productID" : "605C7476-7673-4C62-9E506D4331E03AAE", 
        "title" : "Apple iPad mini 16GB Wi-Fi Space Gray", 
        "price" : 259.99,
        "availableUnits" : 0
      },
    ]
  },
  "eventName" : "/com/products/resaleProducts/",
  "requestParams" : {
    "isSaleItem" : 1
  }
}