5

我转换为控制器以使用 ContentNegotiatingViewResolver 而不是 MessageConverters 来支持多种输出类型。使用 json,我正在使用 MappingJacksonJsonView:

<bean
    class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
    <property name="order" value="1" />
    <property name="mediaTypes">
        <map>
            <entry key="html" value="text/html"/>
            <entry key="json" value="application/json" />
            <entry key="xml" value="application/xml" />
        </map>
    </property>
    <property name="defaultViews">
        <list>
            <bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
            <bean class="org.springframework.web.servlet.view.xml.MarshallingView">
                <constructor-arg>
                    <bean class="org.springframework.oxm.xstream.XStreamMarshaller" />
                </constructor-arg>
            </bean>                         
        </list>
    </property>
    <property name="ignoreAcceptHeader" value="true" />
    <property name="defaultContentType" value="application/json" />
</bean>

使用以下控制器逻辑:

@RequestMapping(value = "/id/{id}", method = RequestMethod.GET)
public ModelAndView getById(@PathVariable (value="id") String id) {
    MyObject ret = doGetById(id);
    ModelAndView modelAndView = new ModelAndView("common/single");
    modelAndView.addObject("myObject", ret);
    return modelAndView;
}

当我访问 /id/1234.json 时返回的 json 类似于:

{
   myObject: {
        field1:"abc",
        field2:"efg"
   }
}

有没有办法让我将 myObject 设置为结果的顶级节点,所以它看起来像这样:

{
    field1:"abc",
    field2:"efg"
}
4

3 回答 3

9

正在发生的事情是 Spring MVC 正在使用 ModelAndView 并将其序列化为 JSON。由于 ModelAndView 看起来就像一张地图,在这种情况下,您在地图中只有一个条目,其键名为 myObject,这就是 JSON 响应所查看的内容。为了只获取您的对象,您需要只返回您的对象而不是 ModelAndView,并让 Jackson 将您的对象序列化为 JSON。

与其返回 ModelAndView,不如返回一个 MyObject 并用 注释该方法@ResponseBody,因此您的控制器方法变为

@RequestMapping(value="/id/{id}", method=RequestMethod.GET, produces="application/json")
public @ResponeBody MyObject getById(@PathVariable (value="id") String id) {
    return doGetById(id);
}
于 2012-07-18T15:19:34.690 回答
2

您应该能够使用以下方法删除外部节点MappingJacksonJsonView.setExtractValueFromSingleKeyModel(true)

设置是否将包含单个属性的模型序列化为映射,或者是否从模型中提取单个值并直接序列化。

设置此标志的效果类似于将 MappingJacksonHttpMessageConverter 与 @ResponseBody 请求处理方法一起使用。

例如:

private final MappingJacksonJsonView view = new MappingJacksonJsonView();

public MyController() {
     view.setExtractValueFromSingleKeyModel(true);
}

@RequestMapping(value = "/id/{id}", method = RequestMethod.GET)
public ModelAndView getById(@PathVariable (value="id") String id) {
    MyObject ret = doGetById(id);
    ModelAndView modelAndView = new ModelAndView();
    modelAndView.setView(this.view);
    modelAndView.addObject("myObject", ret);
    return modelAndView;
}

如果您更喜欢通过配置执行此操作,这也应该有效:

<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView">
    <property name="extractValueFromSingleKeyModel" value="true" />
</bean>
于 2013-08-15T01:13:31.287 回答
2

我遇到了同样的问题,以下解决方案对我有用。

<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView">
   <property name="prefixJson" value="true" />
</bean>
于 2012-07-22T13:49:04.330 回答