Double Quote Avoidance – Using JsonJavaObject + JsonReference to output function references
Recently I have been developing an an XPages UI control for JQuery jqGrid. JqGrid, like most javascript components, relies very much on configuration using json.
I haven’t done much in this area before and I thought things would get pretty ugly if I had to manually output all the javascript / json.
However turns out there are some handy utilities built into the XPages runtime to manage a lot of this for you. This article on Jesse Gallagher’s blog gave me exactly what I needed to get started, and it was super simple to build all these options into a JsonJavaObject or Map
When setting up the columns for JqGrid (the colModel), you can specify properties such as the name and whether it is a key column, what the width is in pixels etc. You can also specify a formatter which will format the cell contents. If you want to use one of the predefined formatters, you can simply refer to the predefined formatter by name, for example here I set up the emailAddress column as editable, with width 120 and formatter “email”
1 2 3 4 5 6 |
JsonJavaObject o = new JsonJavaObject(); o.put("name", "emailAddress"); o.put("editable", true); o.put("formatter", "email"); o.put("width", 120); |
Using the JsonGenerator technique like so (as all examples on this page will do):
1 |
return JsonGenerator.toJson(JsonJavaFactory.instance, o, false); |
This produces the following json:
1 2 3 4 5 6 |
{ "editable":true, "width":120, "formatter":"email", "name":"emailAddress" } |
This works just fine for this situation, however what if we want to define a custom formatter?
In my example, I wanted a custom formatter that would convert the column value into a font awesome icon. I defined a javascript function something like:
1 2 3 4 5 |
function jqFaIconFormatter( cellvalue, options, rowObject ) { return "<i class=\"fa " + cellvalue + "\"/>"; } |
Then I tried to reference it like I did with the built in formatter:
1 2 3 4 |
JsonJavaObject o = new JsonJavaObject(); o.put("name", "someIcon"); o.put("formatter", "jqFaIconFormatter"); |
But had no luck!
1 2 3 4 |
{ "formatter":"jqFaIconFormatter", "name":"someIcon" } |
The Generated Json outputs the function name surrounded in double quotes. This wasn’t a problem with the predefined formatter, my guess is JqGrid internals must be able to look up the predefined formatters by string name. But for custom formatters I think it needs a direct object reference.
My first efforts to figure this out were fruitless, I got a bit down-hearted, I was already behind schedule and thought ‘Nice and neat’ will have to make way for ‘Quick and Dirty’. I started writing ugly code like this:
1 2 3 4 5 6 7 8 9 |
// Note this was not the actual code but you get the idea! ResponseWriter w = context.getResponseWriter(); w.write(" { "); w.write(" \"name\" : \"someIcon\", "); w.write(" \"formatter\": jqFaIconFormatter, "); w.write(" } "); |
Which gave me my desired function reference with no double quotes:
1 2 3 4 |
{ "name":"someIcon", "formatter": jqFaIconFormatter, } |
And it worked! I was in control of whether double quotes would be output or not! But … my anxiety rose every time I saw this code. I decided there must be a solution which would allow me to continue using JsonJavaObjects.
Returning to the problem with a clear head I found the ‘Nice and Neat’ solution!
There is class you can use called com.ibm.commons.util.io.json.JsonReference
You simply create a JsonReference object with a String parameter which will be the desired output.
When the JsonGenerator encounters this, it will know that it should not use double quotes.
Here is the updated example showing the use of the JsonReference:
1 2 3 4 |
JsonJavaObject o = new JsonJavaObject(); o.put("name", "someIcon"); o.put("formatter", new JsonReference("jqFaIconFormatter")); |
and here is the output, with no double quotes, just like we ordered!
1 2 3 4 |
{ "formatter":jqFaIconFormatter, "name":"someIcon" } |
Simarly, imagine you might want to assign an anonymous function as an property, you can use this JsonReference for that too:
1 2 3 4 |
JsonJavaObject o = new JsonJavaObject(); String func = "function () { alert('you clicked?'); }"; o.put("onClick", new JsonReference(func) ); |
generates:
1 2 3 |
{ "onClick":function () { alert('you clicked?'); } } |
Conclusion
If you need to output a Json property without the double quotes: JsonReference is the class for you! Whilst I am doubtful that this is a daily problem for XPages developers, I had trouble when searching for the solution so I thought I would do this post in case it helped anyone else in the future!
Cool!
I use quiet often:
json = (JsonJavaObject) JsonParser.fromJson(factory, colJson);
to create a jsonobject from a notes view column (the column value is a generated json object in text format)
any idea how I could easily verify if a value should set as a normal value or as a JS function in such approach?
Hi Patrick, thanks for the comment!
I have only used it to generate JsonReferences, I haven’t tried parsing them yet.
My best guess would be the opposite of what I’ve demonstrated above. That is, to not have it surrounded in quotes/double quotes it might identify it as a function object.
I’d been interested to hear if that works! Sorry I am not more help.