[coldbox-3.5.0] Returning a query as JSON RESTfully using RELAX

Hi guys,

I am building my first API with Coldbox relax and I am having a bit of an issue getting my responses formatted properly. I apologize if this has been covered already but some prodding in the forum didn’t yield much. Ideally i want to use this API with Christopher Conraets Backbone example (http://coenraets.org/blog/2011/12/backbone-js-wine-cellar-tutorial-part-2-crud/) hence the wine theme. So far I have one relax resource defined:

this.resources = [
{
pattern = “/api/wines”,
handler = “Wine”,
action = “getWines”,
description = “Returns all wines”,
methods = “GET”,
defaultFormat = “json”
}
];

I added the generated route to my routes.cfm file as follows: addRoute(pattern = “/api/wines”, handler = “Wine”, action = “getWines”);

So far so good. Here is the corresponding function in my Wine handler:

And here is the service content (I know it should be in a DAO but I really wanted to get this done :slight_smile:

SELECT * FROM wine WHERE id = ORDER BY country,name

Yet when i try to consume this resource: http:///api/wines.json I get this error:

Complex object types cannot be converted to simple values.

ID: CF_CAST
LINE: 319
Template: C:\inetpub\wwwroot\coldbox\system\Coldbox.cfc

What am I doing wrong? Any help is greatly appreciated!

As you haven’t given the exact error, we can only make an assumption here.

Handlers are still bound by the rules governed by ColdBox, that means the handler needs to something like the following

That’s the basics of it, but you need to look into the return types for others and how this is passed into the handler. But it should be enough to get you going.

Sorry I forgot to change this from

to

You would also need to use event.renderData with type JSON in your controller. Can you share controller code? Thx.

Nolan Dubeau

Load .,8,1

lol, I think that’s what I included in my rewrite to him as well.

The clue is in the error message.

You are returning binary data and not an associate array, which means it can’t be converted to JSon.

Is there a way to tell the JSON cfc to format queries by row rather than by columns? A cluster of objects containing column data is not very useful. Or do i need to create an array of records ahead of time?

Not with the standard way.

The best option would be to create your own requestContext and write the renderData to do this for you, this was one of the reasons that I didn’t like the json.cfc being pulled out of core.

However I am guessing you doing this to use with extJs or maybe jQuery, would that be right?

If so I just might have another solution for you.

I want to use JSON row based objects in backbone.js. I am trying to get through Christopher Conraets ( http://coenraets.org/blog/2011/12/backbone-js-wine-cellar-tutorial-part-2-crud/ ) backbone demo using a Colbox API instead of the PHP one he uses. In the past I have the JSON-simple jar ( http://code.google.com/p/json-simple/ ) to achieve this result and I was wondering if it was loaded in Coldbox or if maybe there was a work around since this is a pretty common need for JSON based data exchanges.

I’d love to hear your idea on how to go about it differently though.

Jean,

I think the most simplest solution, as renderData basically is returning a string and doing an output.

Is to grab the json.cfc from forgebox, or better still the one from http://www.epiphantastic.com/cfjson/ as I think the one from forgeBox checks which version of ColdFusion you are using.

You can then either inject or open this up convert it and output in output tags, and will work.

The problem is very simple, and I made some noise about this. Luis and the others opted to remove that plugin and leave another version in its place, and that version has problems with jQuery, extJs and others that tend to require name and value pair rows.

Now in both extJS and jQuery there is a solution that you can place on the client that will also fix this, with backbone.js you may need to see if something similar can be done there. Both extJS and jQuery can intercept the data and convert it before returning it, so I would assume backbone.js can do the same thing.

So there are a few solutions for you to run with.

Thanks for the advice Andrew but the JSON cfc loaded in Coldbox v 3.5 is CFJSON v1.9 so I think I am going to go with my trusted JSON-simple JAR.

Actually it is a modified version that uses ColdFusion serializeJson, which is why I pointed you back to the original.

It is the ColdFusion’s version of serializeJson that is the problem.

Ah ah! I see it now. How can they even leave the original comments if it’s modified? Now your previous comment makes a lot of sense. Thank you so much for following up.

Well the original blame should be Adobe for making something that would be incompatible with the rest of the world, oh wait they are good at doing that :slight_smile:

Don’t get me wrong, their idea was sound, to reduce the amount of data, but they should have allowed for a switch or something to choose which way we needed it.

I knew this would be a problem with ColdBox moving away from the original for this very reason, but they decided to make it a forgebox thing, which is fair enough. But the problem with using ColdFusion to do the serialization still remains.

OK so in order to hopefully help a fellow developer in the same predicament here is my final solution.

Thanks to Andrew I used the CFJSON code which i copied into a cfc i created and called CFJSON right in my Root/Plugins directory. Then i took a look at the code within the renderData() function to better understand my formattign options.

Finally here is how I leveraged all that in my Wine handler:

local.data = wineService.getWines(); local.cData = getMyPlugin('CFJSON').encode(data = local.data, stringNumbers = true, queryFormat = "array"); event.renderData(data=local.cdata, type="plain", contentType="text/json");

Looks good, and if you want to get even more adventurous you could even DI the plugin.

You can pass the optional JSON query argument to serialized like that

Luis Majano
CEO
Ortus Solutions, Corp
www.ortussolutions.com

ColdBox Platform: http://www.coldbox.org
Linked In: http://www.linkedin.com/pub/3/731/483
Social: twitter.com/ortussolutions | twitter.com/coldbox | twitter.com/lmajano

Problem is though Luis, if you followed the thread the json for renderData uses the ColdFusion SerializeJson functions, that will not work for him.

Luis,

I am not sure i understand, could you please give me an example? If there is a built in way to get to this result you bet i want to know about it :slight_smile:

RenderData() as per the docs, jsonQueryFormat allows you to do encoding for query or array formats

Luis F. Majano
CEO
Ortus Solutions, Corp
www.ortussolutions.com

ColdBox Platform: http://www.coldbox.org
Linked In: http://www.linkedin.com/pub/3/731/483
Blog: http://www.luismajano.com
IECFUG Manager: http://www.iecfug.com

Social: twitter.com/lmajano facebook.com/lmajano