[Coldbox 3.7] Use JSONUtil vs serializeJSON with event.renderData()

What would need to be done to get the event.renderData() function to utilize JSONUtil for JSON serialization versus the native CF serializeJSON. Any thoughts on the best approach to leverage this alternate serializer would be much appreciated.

All of my handlers extend a BaseRemoteHandler.cfc, like Kalen Gibbons demonstrated in his CBDW 2013 presentation on building remote APIs using REST. As a result I hopefully I can just inject a plugin/service object into the base handler to be used in my renderResults() method which is called by the postHandler() and onError() handler methods.

These are internal APIs so we are only needing to return JSON to our client side code.

Thanks,
Tim

We’ve implemented a custom data renderer (see the docs here: http://wiki.coldbox.org/wiki/EventHandlers.cfm#Rendering_Data). In our case, we needed to strip the stupid “secure json” double-whacks off the response before returning it, and found the custom renderer to be a very simple way to do that.

Seems like it could be used in a similar fashion for what you’re wanting.

Hi Joel,

Thanks for the reply. Maybe I’m missing something, but I think essentially that’s what I’m already doing by extending a baseRemoteHandler.cfc and calling event.renderData() within the postHandler() handler method.

Here are my example code snippets to see how I have it setup and what CF is returning vs what I want back.

Example code:

Client.cfc -> basic entity

https://gist.github.com/chair9design/6703566

To implement a custom render type, you basically create a component that implements the $renderData() method, and then pass that as the customer renderer to event.renderData().

I don’t remember where this is documented exactly (or even if it is), but if you search for “$renderData” on this page, it describes it in more detail, along with an example: http://wiki.coldbox.org/wiki/WhatsNew:3.5.0.cfm

So in this custom $renderData(), you could do literally whatever you wanted to do to the content, including serializing it via JSONUtil.cfc

I think the docs do need an update for this…i’ll try to add that in today.

event.renderData(type="plain", data=myCFC, contentType="text");

MyCFC.cfc

Of course I figured it out…for anyone interested see my update below to the renderResults method of my baseRemoteHandler. I switched rendererer to plain and added customer contentType then in my data i just utilize my injected jsonUTIL object and serialize the ret variable using the strict=“true” option of jsonUTIL and it returns properly now.

private any function renderResults(event, required struct ret, numeric statusCode, string statusText){
//writeOutput( jsonUTIL.serialize(var=ret,strict=true));abort;
// render data argument collection
var stArgs = {
“type” = “plain”
,“contentType” = “application/json”
,“data” = jsonUTIL.serialize(var=ret,strict=true)
};
//add statusCode and statusText to argCollection if one was specified explicitly
if (structKeyExists(ARGUMENTS, “statusCode”)) stArgs.statusCode = ARGUMENTS.statusCode;
if (structKeyExists(ARGUMENTS, “statusText”)) stArgs.statusText = ARGUMENTS.statusText;

//finally render it out - this is where CF mangles the json serialization
// HOW CAN I GET THIS TO use JSON UTIL which does it right?
event.renderData(argumentCollection=stArgs);
}

Thanks,
Tim

Thanks a a lot! I’ll look into using this approach as this will give me a little more control than rendering as plain text with a contentType=“application/json”.
I saw that isObject() check inside the DataMarshaller.cfc but didn’t pick up on that was how to implement the custom method.

DataMarshller.cfc -> line 47

`

<cfif isObject( arguments.data ) AND structKeyExists( arguments.data, “$renderdata” )>
<cfreturn arguments.data.$renderdata(argumentCollection=arguments)>

`

-tim

Thanks