2015-05-15 44 views
12

我想写一个Grails REST控制器,它应始终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的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与预期的名称。

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

+1

Accept'header设置为'application/json'吗? – dmahapatro

+0

@dmahapatro我不想使用Accept标头来解析内容,我总是**想要返回JSON。我认为加'静态responseFormats = [“JSON”]'控制器应确保此 –

+0

你能否阐述一下为什么你真的想使用'respond'在所有的一点点?当你不使用不同的MIME类型时,你可以根本不使用'respond'方法,而是使用'render myList as JSON'来代替? –

回答

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的默认响应格式是html,所以如果未指定contentType,它将查找gsp文件进行渲染。

+0

1.我已经有了'Config.groovy' –

+0

2.如果我使用'render someMap作为JSON',那么默认的JSON呈现将被使用,即'TimelineRenderer'不会被调用 –

+0

3.我不需要设置内容类型头,Grails的内容分辨率应该选择基于静态responseFormats = ['' json']' –

6

看起来你必须创建一个空白的(至少)index.gsp

grails-app/views/timeline/ 

,使渲染工作。我成功取回内容类型为application/json

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

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

+0

是的,如果你可以推你的虚拟应用程序到GitHub和/或提出一个非常有用的JIRA。自己做了一些研究后,我开始怀疑不可能有一个类型的容器渲染器,除非你也有一个单独的渲染器用于该类型。然而,文档没有提到这一点,我也没有看到这种情况的逻辑原因,所以我同意这是值得的JIRA。 –

+0

应用程序与问题中描述的内容类似。这是github中的问题。 https://github.com/grails/grails-core/issues/716 – dmahapatro

+1

JIRA问题和演示应用程序的好工作,我已经添加了对该问题的评论 –