2012-08-09 3 views
7

Im Frühjahr MVC 3.x Ich kann eine ContentNegotiatingViewResolver Bean konfigurieren, um automatisch jeden gegebenen Endpunkt in JSON oder XML zu rendern, einfach durch Ändern der Dateierweiterung in .json oder .xml. Ich nahm an, dass es in Grails eine äquivalente Funktionalität gab, aber ich kann sie nicht finden.Grails 2 - produzieren automatisch JSON-Ausgabe (wie Spring 3.x tut)

Alles, was ich gelesen habe, sagt, ich habe den eingehenden MIME-Typen zu fangen (mit withFormat) und dann der JSON Ausgabe angeben mit render as JSON (oder gleichwertig) in jedem meiner Controller-Methoden (z rendering JSON with Grails?). Bevor ich einschließe und JSON-spezifischen Code zu meinen Controllern hinzufüge, dachte ich, ich würde sie hier fragen ...

Meine Frage ist also: Kann ich Grails 2 so konfigurieren, dass automatisch JSON-Ausgabe durch einfaches Hinzufügen eines `.json erzeugt wird Dateierweiterung (oder Ändern der Accept-Header) für eine bestimmte URL?

+1

Wenn Sie noch ein Gerüst verwenden, können Sie es einfach zum Gerüst hinzufügen und es wird auf alle Ihre Controller angewendet. – cdeszaq

Antwort

7

Ich glaube, Sie können easly es mit grails filter

Dies ist ein Filter I ab OAuth API in einer Mine Anwendung getan haben, es xml tun, json und Yalm basierend auf akzeptieren Header

class RenderFilters { 

    def grailsApplication 

    def filters = { 

     multiFormat(controller: '*EndPoint', action: '*', search: true) { 

      after = { Map model -> 

       def accepts = request.getHeaders('accept')*.toLowerCase() 

       def out = model.containsKey('out')?model.out:model 

       if(accepts.any{ it.contains('json') }){ 
        render(text: out as JSON, contentType: 'application/json', encoding:"UTF-8") 
       } 

       else if(accepts.any{ it.contains('yaml') }){ 
        render(text: Yaml.dump(out), contentType: 'application/x-yaml;', encoding:"UTF-8") 
       } 

       else if(accepts.any{ it.contains('html') }){ 
        render(text: out as JSON, contentType: 'application/json', encoding:"UTF-8") 
       } 

       else if(accepts.any{ it.contains('xml') }){ 
        render(text: out as XML, contentType: 'application/xml', encoding:"UTF-8") 
       } 

       else { 
        render(text: out as JSON, contentType: 'application/json', encoding:"UTF-8") 
       } 
       false 
      } 

      before = { 

       def contentType = request.getHeader('Content-Type')?.toLowerCase() 

       if(!contentType) return true 

       if(contentType == 'application/json'){ 
        params.body = JSON.parse(request.reader)      
        } 
       if(contentType == 'application/xml'){ 
        params.body = XML.parse(request.reader) 
        } 
       if(contentType == 'application/x-yaml'){ 
        params.body = Yaml.load(request.reader) 
        } 

       params.body = new TypeConvertingMap((Map) params.body)    

       true 
       } 

     } 

    } 
} 
+0

Das sieht nach dem Weg aus. Ich werde es am Montag versuchen, bevor ich es richtig akzeptiere. Es hat sogar den Vorteil, dass ich einen JSONP-Callback-Wrapper hinzufügen kann! – nickdos

3

Für jeden, der auf diese SO-Frage stieß, dachte ich, ich würde meinen finalen Grails-Filtercode (Version 2.x) einfügen, da er sich von dem in Fabianos Antwort (oben) unterscheidet.

Die folgenden Filter erlauben einfache HTML-Inhalte als normal von Grails und verwendet, um den Inhalt Grails Verhandlungsmechanismus, um die durch response.format Dateierweiterung oder Header annehmen behandelt werden (abhängig von den Conf Einstellungen: grails.mime.use.accept.header & grails.mime.file.extensions). Ich habe auch Unterstützung für einen JSONP-Callback-Wrapper hinzugefügt.

import grails.converters.JSON 
import grails.converters.XML 

class RenderFilters { 

    def filters = { 
     multiFormat(controller: '*', action: '*', find: true) { 
      after = { Map model -> 
       def out = model?.containsKey('out')?model.out:model 

       if (response.format == "json" && params.callback) { 
        render(text: params.callback + "(${out as JSON})" , contentType: 'application/javascript', encoding:"UTF-8") 
        false 
       } else if (response.format == "json") { 
        render(text: out as JSON, contentType: 'application/json', encoding:"UTF-8") 
        false 
       } else if (response.format == "xml") { 
        render(text: out as XML, contentType: 'application/xml', encoding:"UTF-8") 
        false 
       } 
      } 
     } 
    } 
} 
2

Durch Zufall entdeckte ich, dass die neuesten grails Ausgabe JSON und XML, indem Sie einfach die auf der Abfrage Accept-Header funktioniert automatisch!

Ich benutze 2.3.2 im Moment, aber wahrscheinlich das gleiche funktioniert für frühere Versionen und ich habe einfach eine neue App erstellt, erstellt eine neue einfache Domain-Klasse mit einigen Eigenschaften, rannte generate-all und dann run-app. Nach dem Ausführen gibt curl -i -H "Accept: application/json" JSON zurück und curl -i -H "Accept: application/xml" gibt XML ohne zusätzliche Arbeit zurück.

Ich war so überrascht, dass, um sicherzustellen, dass ich nicht etwas seltsames auf meinem lokalen Rechner installiert habe, habe ich es auf einem brandneuen Server mit einer neuen Grals-Installation versucht ... und es funktioniert !!!

Verwandte Themen