2010-02-14 3 views
3

Je voudrais rendre un type complexe, en utilisant la méthode de rendu JSON dans Grails, similaire à la sortie JSON ci-dessous:Comment faire pour rendre dynamiquement JSON complexe avec Grails 1.2?

{"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"}]}]} 

Et je l'ai essayé de faire cela avec le code suivant, où l'auteur et du livre sont classes de domaine contenant les propriétés id et name et où Author hasMany Books (association).

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 
     } 
     } 
    } 
    }  
} 

Il fonctionne très bien avec seuls auteurs, mais pas lorsque je tente de parcourir les livres de chaque auteur et de rendre ceux aussi bien, le code sûr.

Des idées?

question Mise à jour avec code final

Merci à la réponse de Dave J'ai fini avec le code suivant qui fonctionne comme prévu:

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 

Répondre

10

je trouve le constructeur JSON très difficile à utiliser pour obtenir la résultats souhaités donc I prefer to generate the results in maps and lists and then render those.

En ayant quelque chose comme ce qui suit (avertissement: code non testé):

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 

Je pense que vous rendre le code plus facile à lire et à réutiliser et il devrait faire ce que vous voulez (mes fautes de frappe permet).

Si vous voulez toujours rendre vos auteurs et vos livres dans le même format JSON, vous pouvez considérer registering a custom JSON object marshaller in Bootstrap.groovy. En résumé quelque chose comme travaillerait:

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

Avoir une propriété de livres sur votre auteur faciliterait encore les choses!

Questions connexes