Grails - grails.converters.JSON - removing the class name
Is there a way to remove the class field in a JSON converter?
Example:
import testproject.*
import grails.converters.*
emp = new Employee()
emp.lastName 开发者_运维问答= "Bar"
emp as JSON
as a string is
{"class":"testproject.Employee","id":null,"lastName":"Bar"}
I'd prefer
{"id":null,"lastName":"Bar"}
Is there a way to add one more line of code at the end to remove the class field?
Here is yet one way to do it. I've added a next code to the domain class:
static {
grails.converters.JSON.registerObjectMarshaller(Employee) {
return it.properties.findAll {k,v -> k != 'class'}
}
}
But as I found if you have used Groovy @ToString class annotation when you also must add 'class' to excludes parameter, e.g.:
@ToString(includeNames = true, includeFields = true, excludes = "metaClass,class")
My preferred way of doing this:
def getAllBooks() {
def result = Book.getAllBooks().collect {
[
title: it.title,
author: it.author.firstname + " " + it.author.lastname,
pages: it.pageCount,
]
}
render(contentType: 'text/json', text: result as JSON)
}
This will return all the objects from Book.getAllBoks() but the collect method will change ALL into the format you specify.
One alternative is to not use the builder:
def myAction = {
def emp = new Employee()
emp.lastName = 'Bar'
render(contentType: 'text/json') {
id = emp.id
lastName = emp.lastName
}
}
This is a bit less orthogonal since you'd need to change your rendering if Employee changes; on the other hand, you have more control over what gets rendered.
import testproject.*
import grails.converters.*
import grails.web.JSONBuilder
def emp = new Employee()
emp.lastName = "Bar"
def excludedProperties = ['class', 'metaClass']
def builder = new JSONBuilder.build {
emp.properties.each {propName, propValue ->
if (!(propName in excludedProperties)) {
setProperty(propName, propValue)
}
}
render(contentType: 'text/json', text: builder.toString())
@wwarlock's answer is partly right, I have to put the registerObjectMarshaller on Bootstrap, it can work.
def a = Employee.list()
String[] excludedProperties=['class', 'metaClass']
render(contentType: "text/json") {
employees = array {
a.each {
employee it.properties.findAll { k,v -> !(k in excludedProperties) }
}
}
}
This works for me. You can easily pass in any property to exclude. Or turn it around:
def a = Employee.list()
String[] includedProperties=['id', 'lastName']
render(contentType: "text/json") {
employees = array {
a.each {
employee it.properties.findAll { k,v -> (k in includedProperties) }
}
}
}
Beware: This is only for simple objects. If you see "Misplaced key: expected mode of KEY but was OBJECT" this solution is not for you. :)
HP
You can customize the fields to be excluded (including the class name) using the setExcludes method provided in the grails.converters.JSON
def converter = emp as JSON
converter.setExcludes(Employee.class, ["class",""])
and then, you can use it just like according to your requirements,
println converter.toString()
converter.render(new java.io.FileWriter("/path/to/my/file.xml"))
converter.render(response)
精彩评论