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 WebFlux 应用程序不支持 @RestController 映射前缀?