spring mvc restcontroller返回json字符串

Posted

技术标签:

【中文标题】spring mvc restcontroller返回json字符串【英文标题】:spring mvc restcontroller return json string 【发布时间】:2015-07-24 03:49:35 【问题描述】:

我有一个带有以下方法的 Spring MVC 控制器:

@RequestMapping(value = "/stringtest", method = RequestMethod.GET)
public String simpletest() throws Exception 
    return "test";

它位于一个控制器内,以这样的方式开始:

@RestController
@RequestMapping(value = "/root")
public class RootController

当我调用其他返回对象的方法时,Jackson 会将这些对象序列化为 JSON。但是这个返回字符串的方法不会转换为 JSON。如果不清楚,这里有一个使用 curl 的示例:

$curl http://localhost:8080/clapi/root/stringtest 
test

所以问题是没有任何引号的“测试”不是 JSON 字符串,但我的 REST 客户端需要一个字符串。我希望 curl 命令显示带有引号的字符串,所以它是合法的 JSON:

"test"

我正在使用 Spring WebMVC 4.1.3 和 Jackson 2.4.3。我尝试在 RequestMapping 中添加一个“produces”属性来表示它应该返回 JSON。在这种情况下,返回的 Content-Type 属性是“application/json”,但仍然没有引用测试字符串。

我可以通过调用 JSON 库将 Java 字符串转换为 JSON 来解决此问题,但似乎 Spring MVC 和 Jackson 通常会自动执行此操作。然而不知何故,他们并没有在我的情况下这样做。有什么想法我可能配置错了只是测试而不是“测试”?

【问题讨论】:

您可以尝试将您的字符串包装在一个对象中。否则,Jackson 无法知道给字符串的 JSON 键取什么名字。 @Matt 一个单独的字符串是有效的 JSON,它不需要是一个对象。例如,即使是数组也可以正常工作。如果我更改代码以返回一个数组,那么我会得到["test"]。所以我希望如果我返回一个简单的字符串,我应该得到"test" 这不是很明显,看看这个答案:***.com/a/7487892/369946。根据“application/json”媒体类型的RFC定义,JSON应该是一个对象或者一个数组。 @Matt 嗯,我同意。该页面确实提供了一些很好的相反观点。似乎 RFC 和 ECMA-404 不同意,因为 ECMA-404 没有给出这样的限制。因此,如果您遵循 RFC,那么 JSON 必须以 或 [ 开头,但 ECMA-404 规范并非如此。在 javascript 中进行测试时,内置的 JSON.stringify("test")(在 Chrome 和 Safari 上测试)和 AngularJS 的 angular.toJson("test") 都会产生 "test" 作为输出,因此 Javascript Web 实现和 Angular 都相信带引号的字符串是有效的 JSON。不过,如果浏览器和 RFC 相互同意就好了! 【参考方案1】:

事实证明,当您使用@EnableWebMvc 注解时,它会默认打开一堆http 消息转换器。列表中的第二个是StringHttpMessageConverter,文档说它将应用于text/* 内容类型。但是,在调试器单步执行之后,它适用于 */* 内容类型的字符串对象——其中显然包括 application/json

负责application/json 内容类型的MappingJackson2HttpMessageConverter 在此列表中更靠后。所以对于 String 以外的 Java 对象,这个对象会被调用。这就是为什么它适用于 Object 和 Array 类型,但不适用于 String - 尽管有很好的建议使用 producer 属性设置 application/json 内容类型。尽管该内容类型是触发此转换器所必需的,但字符串转换器首先完成了这项工作!

当我为其他配置扩展 WebMvcConfigurationSupport 类时,我覆盖了以下方法以将 Jackson 转换器放在首位,因此当内容类型为 application/json 时,将使用此方法而不是字符串转换器:

@Override
protected void configureMessageConverters(
        List<HttpMessageConverter<?>> converters) 
    // put the jackson converter to the front of the list so that application/json content-type strings will be treated as JSON
    converters.add(new MappingJackson2HttpMessageConverter());
    // and probably needs a string converter too for text/plain content-type strings to be properly handled
    converters.add(new StringHttpMessageConverter());

现在,当我从 curl 调用测试方法时,我得到了所需的 "test" 输出,而不仅仅是 test,因此期待 JSON 的 Angular 客户端现在很高兴。

【讨论】:

【参考方案2】:

试试这个:

@RequestMapping(value = "/stringtest", method = RequestMethod.GET,produces = MediaType.APPLICATION_JSON_VALUE)

【讨论】:

谢谢 Shyam,我已经尝试过了,但它只是将 Content-Type 设置为“application/json”,但不会将我的字符串括在引号中。我确实尝试剪切并粘贴您的建议,以防我输入错误,但它不起作用。【参考方案3】:

试试这样的

@RequestMapping(value = "/stringtest", method = RequestMethod.GET, produces="application/json")
public @ResponseBody String simpletest() throws Exception 
    return "test";

【讨论】:

感谢 Martin,我曾尝试过产生属性,但正如我所提到的,似乎所做的只是将 Content-Type 更改为“application/json”,但输出仍然是 test,没有引号.并且 @ResponseBody 不是必需的,因为我有 @RestController 注释,这使得它自动化。尽管如此,我还是删掉了你的建议,以防我错了,但没有运气。

以上是关于spring mvc restcontroller返回json字符串的主要内容,如果未能解决你的问题,请参考以下文章

Spring @RestController 用于匿名和授权用户的单一方法

Spring 注解中@RestController与@Controller的区别

Spring 注解中@RestController与@Controller的区别

Spring 注解中@RestController与@Controller的区别

Spring中@Controller和@RestController之间的区别

Spring @RestController 生成没有命名空间的 XML