7

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

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

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

4

3 回答 3

7

我认为您可以使用grails 过滤器轻松实现

这是我在我的应用程序中通过 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
                }

        }

    }
}
于 2012-08-09T08:26:35.733 回答
3

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

以下过滤器允许 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
                }
            }
        }
    }
}
于 2012-08-13T04:13:02.953 回答
2

偶然地,我发现最新的 grails 只需在查询中设置 Accept 标头即可自动输出 JSON 和 XML!

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

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

于 2013-11-18T23:47:42.310 回答