我试图编写一个始终应该使用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>
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具有预期的名称。
我强烈怀疑这个问题与使用自定义渲染器有关,因为我有另一个几乎完全相同的控制器,它没有使用自定义渲染器,而且它正确地解析了内容类型。
答案 0 :(得分:6)
看起来你必须在
下创建一个空白(至少)index.gsp
grails-app/views/timeline/
使渲染器工作。我已成功将内容类型恢复为application/json
这种行为让我感到困惑,我仍然在研究它。这值得JIRA问题。如果你需要我可以将我的虚拟应用程序推送到github。
<强>更新强>
在github中创建的问题(带有示例应用程序的链接)
https://github.com/grails/grails-core/issues/716
答案 1 :(得分:0)
在Config.groovy中,需要指定grails.mime.types
。
详细信息可以在这里找到:Grails 2.3.11 Content Negotiation。至少你需要在Config.groovy中拥有以下内容:
grails.mime.types = [
json: ['application/json', 'text/json']
]
如果您想使用自定义JSON进行回复,建议使用render someMap as JSON
。
关于您的404问题,您需要在控制器操作中执行response.setContentType('application/json')
。 Grails的&#39;默认响应格式为html,因此如果未指定contentType,它将查找要呈现的gsp文件。