Grails REST控制器响应的内容类型不正确

时间:2015-05-15 16:59:14

标签: rest grails

我试图编写一个始终应该使用JSON响应的Grails REST控制器。控制器如下所示:

class TimelineController {

    static allowedMethods = [index: "GET"]
    static responseFormats = ['json']

    TimelineService timelineService

    def index(TimeLineCommand command) {
        List<TimelineItem> timeline = timelineService.currentUserTimeline(command)
        respond timeline
    }
}

我使用的是respond方法,这是Grails&#39;的一部分。 REST支持,因此内容协商用于确定要呈现的响应类型。在这种特殊情况下,我希望选择JSON,因为控制器指定

    static responseFormats = ['json']

此外,我已经编写了(并在Spring上注册)以下渲染器来自定义为List<TimelineItem>

返回的JSON格式
class TimelineRenderer implements ContainerRenderer<List, TimelineItem> {

    @Override
    Class<List> getTargetType() {
        List
    }

    @Override
    Class<TimelineItem> getComponentType() {
        TimelineItem
    }

    @Override
    void render(List timeline, RenderContext context) {

        context.contentType = MimeType.JSON.name
        def builder = new JsonBuilder()

        builder.call(
            [items: timeline.collect { TimelineItem timelineItem ->

                def domainInstance = timelineItem.item

                return [
                        date: timelineItem.date,
                        type: domainInstance.class.simpleName,
                        item: [
                                id   : domainInstance.id,
                                value: domainInstance.toString()
                        ]
                ]
            }]
        )

        builder.writeTo(context.writer)
    }

    @Override
    MimeType[] getMimeTypes() {
        [MimeType.JSON] as MimeType[]
    }
}

我已经编写了一些功能测试,并且可以看到虽然我的渲染器被调用,但已解析的内容类型为text/html,因此控制器返回404,因为它无法找到GSP具有预期的名称。

我强烈怀疑这个问题与使用自定义渲染器有关,因为我有另一个几乎完全相同的控制器,它没有使用自定义渲染器,而且它正确地解析了内容类型。

2 个答案:

答案 0 :(得分:6)

看起来你必须在

下创建一个空白(至少)index.gsp
grails-app/views/timeline/

使渲染器工作。我已成功将内容类型恢复为application/json

这种行为让我感到困惑,我仍然在研究它。这值得JIRA问题。如果你需要我可以将我的虚拟应用程序推送到github。

<强>更新
在github中创建的问题(带有示例应用程序的链接) https://github.com/grails/grails-core/issues/716

答案 1 :(得分:0)

  1. 在Config.groovy中,需要指定grails.mime.types。 详细信息可以在这里找到:Grails 2.3.11 Content Negotiation。至少你需要在Config.groovy中拥有以下内容:

    grails.mime.types = [
        json: ['application/json', 'text/json']
    ]
    
  2. 如果您想使用自定义JSON进行回复,建议使用render someMap as JSON

  3. 关于您的404问题,您需要在控制器操作中执行response.setContentType('application/json')。 Grails的&#39;默认响应格式为html,因此如果未指定contentType,它将查找要呈现的gsp文件。