Grails 2 - 自动生成 JSON 输出(就像 Spring 3.x 一样)

Posted

技术标签:

【中文标题】Grails 2 - 自动生成 JSON 输出(就像 Spring 3.x 一样)【英文标题】:Grails 2 - produce JSON output automatically (like Spring 3.x does) 【发布时间】:2012-08-06 06:35:15 【问题描述】:

在 Spring MVC 3.x 中,我可以配置一个 ContentNegotiatingViewResolver bean 来自动以 JSON 或 XML 格式呈现任何给定的端点,只需将文件扩展名更改为 .json.xml。我以为 Grails 中有一个等效的功能,但我找不到。

我读过的所有内容都说我必须捕获传入的 mime 类型(使用 withFormat),然后在我的每个控制器方法中使用 render as JSON(或等效项)指定 JSON 输出(例如 rendering JSON with Grails? )。在我开始向我的控制器添加特定于 JSON 的代码之前,我想我会在这里问...

所以我的问题是:我能否通过简单地为任何给定 URL 添加一个 `.json' 文件扩展名(或更改接受标头)来配置 Grails 2 以自动生成 JSON 输出?

【问题讨论】:

如果你还在使用脚手架,你可以把它添加到脚手架上,它会应用到你所有的控制器上。 【参考方案1】:

我认为您可以使用 grails filter 轻松访问它

这是我在我的应用程序中通过 OAuth API 完成的过滤器,它基于接受标头执行 xml、json 和 yalm

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
                

        

    

【讨论】:

这看起来像是要走的路。在接受正确之前,我会在星期一试一试。它甚至具有允许我添加 JSONP 回调包装器的优势!【参考方案2】:

对于遇到这个 SO 问题的任何人,我想我会包含我的最终 Grails(版本 2.x)过滤器代码,因为它与 F***o 的回答(上图)中的代码确实不同。

以下过滤器允许 Grails 正常处理纯 HTML 内容,并使用 Grails 内容协商机制通过文件扩展名或接受标头设置 response.format(取决于 conf 设置:grails.mime.use.accept.header & grails.mime.file.extensions )。我还添加了对 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
                
            
        
    

【讨论】:

【参考方案3】:

我偶然发现最新的 grails 通过简单地在查询中设置 Accept 标头就可以自动输出 JSON 和 XML!

我目前使用的是 2.3.2,但可能与早期版本相同,我只是创建了一个新应用程序,创建了一个具有一些属性的新简单域类,运行 generate-all 然后运行应用程序。运行后, curl -i -H "Accept: application/json" 返回 JSON, curl -i -H "Accept: application/xml" 返回 XML,无需任何额外工作。

我对此感到非常惊讶,为了确保我没有在我的本地机器上安装奇怪的东西,我在安装了新 grails 的全新服务器上尝试了它......它可以工作!!!

【讨论】:

以上是关于Grails 2 - 自动生成 JSON 输出(就像 Spring 3.x 一样)的主要内容,如果未能解决你的问题,请参考以下文章

如何压缩来自 grails 控制器的输出?

在 Groovy/Grails 中使用 JSON 创建对象

Grails 无法将 JSON 中的日期/时间解组回 joda DateTime

Grails 3 响应方法不使用定义的 JSON 编组器格式

Grails - 将 UUID 呈现为 JSON

使用 Grails 在服务器端获取 JSON 数据