Как динамически отобразить сложный JSON с Grails 1.2? - PullRequest
3 голосов
/ 14 февраля 2010

Я хотел бы визуализировать сложный тип, используя метод визуализации JSON в Grails, аналогично приведенному ниже выводу 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 

1 Ответ

10 голосов
/ 15 февраля 2010

Мне очень сложно использовать JSON-конструктор для получения желаемых результатов, поэтому Я предпочитаю генерировать результаты в картах и ​​списках, а затем отображать их .

Имея что-то вроде следующего (предупреждение: непроверенный код!):

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, вы можете зарегистрировать собственный маршаллер объекта JSON в Bootstrap.groovy . В общем, что-то вроде бы будет работать:

    JSON.registerObjectMarshaller(Author) {
        def returnArray = [:]
        returnArray['id'] = it.id
        returnArray['name'] = it.name
        return returnArray
    }

Кроме того, если у вашего автора есть свойство books, все еще будет проще!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...