Fun with Grails JSON conversion
I discovered a problem this afternoon with how one of the domain objects in my Grails app was being converted to JSON in its controller. The conversion functioned as expected in a unit test, but failed in integration tests and when running the real app. “Time to see how good the debugger in Intellij 9 is,” I say to myself. So I dive into the grails.converters.JSON class to try to find where the difference comes from. Unfortunately, every time I step into the render() method, the rendering quickly fails with this exception:
org.codehaus.groovy.grails.web.json.JSONException: “Misplaced object”
It turns out that the JSON converter has a writer property that is a JSONWriter object. The act of showing the writer in the variables window of the Intellij debugger causes its toString() method to be called by the IDE (though any breakpoints set in the class do not get triggered by the call). This, in turn, causes the writer to actually do the writing of the object which, when complete, changes the writer’s state property to DONE. When the real code execution tries to process the data, the JSONWriter throws the exception because it thinks it has already finished rendering.
The trick to step through the JSON converter is to define a custom Type Renderer for the JSONWriter class that does not invoke the “toString” method. A blog post on the Intellij site defines how to setup a Type Renderer for a class. I set mine up so that the node renders simply as “JSONWriter” since I don’t need to see the details for it. One caveat though – I found that the new Type Renderer didn’t affect entries already in my variables window until I right-clicked one and selected “View As -> JSONWriter”. Then the view changed to use the new display settings.
Now back to debugging…maybe I’ll actually figure out the real problem sometime before the sun comes up.