【发布时间】:2015-07-27 16:47:48
【问题描述】:
我正在尝试编写一个应始终以 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。
我强烈怀疑这个问题与使用自定义渲染器有关,因为我有另一个几乎相同的控制器,它不使用自定义渲染器并且它正确解析了内容类型。
【问题讨论】:
-
Accept标头是否设置为application/json? -
@dmahapatro 我不想使用
Accept标头进行内容解析,我总是想返回 JSON。我认为将static responseFormats = ['json']添加到控制器应该可以确保这一点 -
您能否详细说明一下您究竟为什么要使用
respond?当您不使用不同的 mime 类型时,您可以完全摆脱respond方法,而改用render myList as JSON? -
@MarioDavid 因为如果
respond被调用,Grails 将使用我的自定义渲染器来生成 JSON。如果我使用myList as JSON,那么将使用默认渲染器。 -
应该创建一个 JIRA 问题。我可以在 2.4.4 和 2.5.0 中复制它。仍在调查中。