2012-08-09 14 views
7

En Spring MVC 3.x puedo configurar un bean ContentNegotiatingViewResolver para representar automáticamente cualquier punto final dado en JSON o XML simplemente cambiando la extensión de archivo a .json o .xml. Supuse que había una funcionalidad equivalente en Grails, pero no puedo encontrarla.Grails 2: produce salida JSON automáticamente (como Spring 3.x)

Todo lo que he leído dice que tengo que coger el tipo MIME entrante (usando withFormat) y especifique la salida JSON usando render as JSON (o equivalente) en cada uno de mis métodos de controlador (por ejemplo rendering JSON with Grails?). Antes de sumergirme y comenzar a agregar código específico de JSON a mis controladores, pensé en preguntar aquí ...

Así que mi pregunta es: ¿Puedo configurar Grails 2 para producir automáticamente salida JSON simplemente agregando un `.json 'extensión de archivo (o cambiar el encabezado de aceptar) para cualquier URL dada?

+1

Si todavía está utilizando andamios, puede simplemente agregarlo al andamio y se aplicará a todos sus controladores. – cdeszaq

Respuesta

7

creo que se puede easly a él mediante un grails filter

Este es un filtro que he hecho ab OAuth API en una aplicación de la mina, que haga XML, JSON y Y'allways Y'allywood basado en aceptar las cabeceras

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

Esto parece ser el camino a seguir. Lo intentaré el lunes antes de aceptar como correcto. ¡Incluso tiene la ventaja de permitirme agregar un contenedor de devolución de llamada JSONP! – nickdos

3

Para cualquier persona que se encuentre con esta pregunta TAN, pensé que incluiría mi código de filtro final Grails (versión 2.x), ya que difería de la respuesta de Fabiano (arriba).

El siguiente filtro permite que el contenido HTML plano a ser manejado como normales por Grails y utiliza el mecanismo de negociación de contenido Grails para establecer el response.format por extensión de archivo o aceptar cabecera (dependiendo de la configuración conf: grails.mime.use.accept.header & grails.mime.file.extensions). También agregué soporte para un contenedor de devolución de llamada JSONP.

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

Por accidente, descubrí que las últimas griales hace de salida JSON y XML de forma automática, simplemente definiendo el encabezado Accept en la consulta!

Estoy usando 2.3.2 por el momento, pero probablemente lo mismo funcione para versiones anteriores y simplemente creé una nueva aplicación, creé una nueva clase de dominio simple con algunas propiedades, ejecuté generate-all y luego run-app. Después de ejecutarlo, el curl -i -H "Accept: application/json" devuelve JSON y curl -i -H "Accept: application/xml" devuelve XML sin ningún trabajo adicional.

Estaba tan sorprendido con esto, que para asegurarme de no haber instalado algo extraño en mi máquina local, lo intenté en un nuevo servidor con una nueva instalación de grails ... y funciona !!!