Reputation: 32076
Came across this strange result today trying to render a list of objects as JSON in Grails 2.0.4...(i know i'm gonna regret asking this on account of something right under my nose...updated 5/26, my prediction was correct, see below :-))
This works fine; the JSON renders correctly in the browser...
def products = [] //ArrayList of Product objects from service
def model = (products) ? [products:products] : [products:"No products found"]
render model as JSON
..so why doesn't this shortened version without model
work?
def products = []
render ((products) ? [products:products] : [products:"No products found"]) as JSON
The resulting JSON from the above code is output as a single line of text, so I suspect it's not picking up as JSON
, but it's parenthesized correctly, so what's the deal?
['products':[com.test.domain.Product : null, com.test.domain.Product...]
Upvotes: 5
Views: 1544
Reputation: 122374
The essence of your problem here is that the groovy compiler interprets
render x as JSON
to mean
render (x as JSON)
but it interprets
render (x) as JSON
to mean
(render x) as JSON
If a method name (in this case render
) is followed immediately by an opening parenthesis, then only code up to the matching closing parenthesis is considered to be the argument list. This is why you need an extra set of parentheses to say
render ((x) as JSON)
Upvotes: 3
Reputation: 50245
This is a normal behavior of render
. When you provide arguments to render
without braces like
render model as JSON
It makes an implicit adjustment setting up the content-type
to text/json
. But in the later case, you have unknowingly made the render
to use the braces like [mark on the first brace after render
makes render use the normal render()
]
render ((products) ? [products:products] : [products:"No products found"]) as JSON
.
In the above case, you have to pass in the named parameters to render
mentioning the contentType
, text
or model
, status
etc. So in order to render the inline control logic as JSON in browser/view you have to do like below:
render(contentType: "application/json", text: [products: (products ?: "No products found")] as JSON)
You can also use content-type
as text/json
. I prefer application/json
.
UPDATE
Alternative Simplest Way:
render([products: (products ?: "No products found")] as JSON)
Upvotes: 8
Reputation: 431
What you do is calling render with the parameters in ( ), and then applying "as JSON" to the result!
Don't forget that leaving the parentheses out is just a shortcut for a method call, but the same rules still apply.
Upvotes: 1
Reputation: 3552
Don't know the reason. Try to use like this:
render(contentType: 'text/json') {[
'products': products ? : "No products found"
]}
Upvotes: 1