我想使用Grails中的JSON渲染方法来渲染复杂的类型,类似于下面的JSON输出:
{
"authors": [{
"id": 1,
"name": "Author 1",
"books": [{
"id": 1,
"name": "Book 1"
}, {
"id": 2,
"name": "Book 2"
}]
}, {
"id": 2,
"name": "Author 2",
"books": [{
"id": 1,
"name": "Book 1"
}, {
"id": 2,
"name": "Book 2"
}]
}]
}
而且我尝试使用以下代码来执行此操作,其中Author和Book是包含属性id和name的域类,而Author具有很多书(关联)。
def results = Authors.list()
render(contentType:"text/json") {
authors = array {
for(a in results) {
author id:a.id, name:a.name, books: array = {
def bookresults = Book.findAllByAuthor(a)
for(b in bookresults) {
book id:b.id, name:b.name
}
}
}
}
}
[它单独对作者有效,但是当我尝试遍历每位作者的书并同时渲染这些书时,代码将失败。
有什么想法吗?
更新后的问题以及最终代码
由于戴夫的回答,我得到了下面的代码,该代码可以正常工作:
def authors = []
for (a in Author.list()) {
def books = []
def author = [id:a.id, name:a.name, books:books]
for (b in Book.findAllByAuthor(a)) {
def book = [id:b.id, name:b.name]
books << book
}
authors << author
}
def items = [authors:[authors]]
render items as JSON
我发现很难使用JSON构建器来获得所需的结果,所以I prefer to generate the results in maps and lists and then render those。
具有类似以下内容的警告(警告:未经测试的代码!):
def results = []
Authors.list()?.each{ author ->
def authorResult = [id:author.id, name:author.name]
Book.findAllByAuthor(author)?.each { book ->
authorResultput('books', [id:book.id, name:book.name])
}
results << authorResult
}
def authors = [authors: results]
render authors as JSON
我认为您使代码更易于阅读和重用,并且应该按照您想要的做(我的错别字允许。)>
[如果您始终要以相同的JSON格式呈现您的作者和书籍,则可以考虑registering a custom JSON object marshaller in Bootstrap.groovy。总之,类似的东西会起作用:
JSON.registerObjectMarshaller(Author) { def returnArray = [:] returnArray['id'] = it.id returnArray['name'] = it.name return returnArray }
还拥有您的作者的书本属性将使事情变得更加简单!