2015-05-15 35 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問題和演示應用程序的好工作,我已經添加了對該問題的評論 –