如何使用Grails 1.2动态呈现复杂的JSON?

问题描述 投票:4回答:1

我想使用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 grails
1个回答
10
投票

我发现很难使用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
    }

还拥有您的作者的书本属性将使事情变得更加简单!

© www.soinside.com 2019 - 2024. All rights reserved.