在spring mvc @ResponseBody中返回文字JSON字符串
Posted
技术标签:
【中文标题】在spring mvc @ResponseBody中返回文字JSON字符串【英文标题】:Return literal JSON strings in spring mvc @ResponseBody 【发布时间】:2013-03-08 13:47:14 【问题描述】:我将对象作为 JSON 字符串存储在我的数据库中。我想制作一个公开这些字符串的 REST 服务。然而,当我编写我的方法时,我得到的字符串的引号被转义了。例如,我包含了一个返回字符串的方法,
@RequestMapping(value = "test", method = RequestMethod.GET)
public @ResponseBody
String getTest()
return "\"a\":1, \"b\":\"foo\"";
但是当我在浏览器中调用此方法时,当我真正想要发生的是 "a ": 1, "b": "foo"。我认为“字符串”作为返回类型可能是问题所在,但我还能做什么?包装类做同样的事情:
"value" : "\"a\":1, \"b\":\"foo\""
我可以序列化它然后返回对象,但这似乎有点荒谬。 这可能是我的配置文件的相关部分:
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters)
super.configureMessageConverters(converters);
converters.add(mappingJacksonHttpMessageConverter());
@Bean
MappingJacksonHttpMessageConverter mappingJacksonHttpMessageConverter()
MappingJacksonHttpMessageConverter mappingJacksonHttpMessageConverter = new MappingJacksonHttpMessageConverter();
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
mappingJacksonHttpMessageConverter.setObjectMapper(objectMapper);
mappingJacksonHttpMessageConverter.setPrettyPrint(true);
return mappingJacksonHttpMessageConverter;
谢谢
编辑:正如下面所建议的,字符串似乎被双重编码。注释掉我的配置中的 2 个类可以解决这个问题。但是,我仍然有其他地方想要返回对象,并希望让那些通过我知道在哪里配置的通用序列化 bean 运行。所以我认为我的选择是: a)自己做所有的序列化。所有的方法都返回字符串,那些已经是 JSON 的返回自己,那些是对象的都返回 JSONUtil.toJson(object)。我不喜欢这种方法,但我知道它会起作用。 b) 使用看起来像这样的包装类:
public static class Wrapper
@JsonRawValue
private final String value;
这导致前面有一个尴尬的“价值”,尽管这没有真正的意义。
基本上我想要的是@JsonRawValue,但是让它在 RequestMapping 方法而不是属性上工作。 想法?意见?其他建议?
【问题讨论】:
【参考方案1】:这适用于 Jackson 2(至少):
@Controller
public class YourController
@RequestMapping(..)
public @ResponseBody Json get()
return new Json(" \"attr\" : \"value\" ");
class Json
private final String value;
public Json(String value)
this.value = value;
@JsonValue
@JsonRawValue
public String value()
return value;
不是特别漂亮,但很有效。我只希望 Spring 支持这个:
@RequestMapping(..)
public @JsonRawValue @ResponseBody String get()
// ...
【讨论】:
帮助很大。过去 3 年有什么变化吗? @Kulpemovitz 我不知道【参考方案2】:您的问题的解决方案是,无需更改任何配置即可完美运行
import com.fasterxml.jackson.databind.JsonNode;
import com.github.fge.jackson.JsonLoader;
JsonNode getTest()
return JsonLoader.fromString("\"a\":1, \"b\":\"foo\"");
【讨论】:
【参考方案3】:如果您想在浏览器中将 JSON 字符串转换为 JSON 对象,请将字符串转换器放在 Jackson 转换器之前。 请按照此link 获取完整示例。它适用于自定义转换器配置和弹簧验证。
有效
converters.add(stringConverter());
converters.add(mappingJackson2HttpMessageConverter());
super.configureMessageConverters(converters);
没有
converters.add(mappingJackson2HttpMessageConverter());
converters.add(stringConverter());
super.configureMessageConverters(converters);
【讨论】:
这对我来说是个问题。更改插入列表的顺序解决了这个问题。 +1【参考方案4】:今天我们遇到了同样的问题,并通过多个转换器解决了这个问题。现在每个String
都将被视为一个字符串,而其他每个Object
都将被Jackson 序列化。这允许在 Spring 控制器中手动(通过返回 String
)或自动(通过返回其他内容)进行序列化。
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters)
converters.add(stringConverter());
converters.add(mappingJackson2HttpMessageConverter());
super.configureMessageConverters(converters);
@Bean
public StringHttpMessageConverter stringConverter()
final StringHttpMessageConverter stringConverter = new StringHttpMessageConverter(UTF_8);
stringConverter.setSupportedMediaTypes(Arrays.asList(
MediaType.TEXT_PLAIN,
MediaType.TEXT_html,
MediaType.APPLICATION_JSON));
return stringConverter;
@Bean
public GenericHttpMessageConverter<Object> mappingJackson2HttpMessageConverter()
final ObjectMapper objectMapper = objectMapperBuilder().build();
final MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(objectMapper);
return converter;
【讨论】:
【参考方案5】:就我而言,我希望响应类型由请求参数确定,因此必须在代码中指定内容类型,例如:
@RequestMapping("/myurl")
public void radiusSearch(@RequestParam responseType, HttpServletResponse response) throws IOException
String jsonResponse = makeSomeJson();
response.setContentType(responseType);
try
response.getOutputStream().write(jsonResponse.getBytes());
finally
response.getOutputStream().close();
【讨论】:
【参考方案6】:我知道这是一个老问题,但我自己只是在处理相反的问题(我正在返回一个字符串并希望它转换为 JSON)。在您的情况下,听起来您只是希望将您的 String 视为纯字符串,而不是对其进行任何类型的 JSON 转换,因为您已经拥有 JSON。
因此,在您的情况下,您不想使用 MappingJacksonHttpMessageConverter
(如果您现在使用的是 Jackson2,则不要使用 MappingJackson2HttpMessageConverter
)。您根本不希望进行任何转换,并且该转换器将 Java 对象转换为 JSON 或从 JSON 转换。因此,您应该只使用普通的StringHttpMessageConverter
。你可以通过改变你的设置方法来做到这一点:
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters)
converters.add(new StringHttpMessageConverter());
此转换器适用于*/*
类型(文件不正确,上面写着text/*
,我在调试器中发现了困难的方法)。因此,无论您的内容类型是否为 application/json
,如果您使用此转换器,无论哪种方式 Spring 都不会弄乱您的字符串。
【讨论】:
【参考方案7】:我猜你想要的是产生一个内容类型为application/json
的响应。在您的情况下,当您将 json-data 作为原始字符串时,请执行以下操作:
在您的控制器中将produces="application/json"
添加到您的@RequestMapping
属性:
@RequestMapping(value = "test", method = RequestMethod.GET, produces="application/json")
public @ResponseBody
String getTest()
return "\"a\":1, \"b\":\"foo\"";
然后您必须配置StringHttpMessageConverter
以接受 application/json 媒体类型。
使用 Java 配置:
@Override
public void configureMessageConverters(
List<HttpMessageConverter<?>> converters)
StringHttpMessageConverter stringConverter = new StringHttpMessageConverter(
Charset.forName("UTF-8"));
stringConverter.setSupportedMediaTypes(Arrays.asList( //
MediaType.TEXT_PLAIN, //
MediaType.TEXT_HTML, //
MediaType.APPLICATION_JSON));
converters.add(stringConverter);
使用 XML 配置:
<bean class = "org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<array>
<bean class = "org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes" value="application/json; charset=UTF-8" />
</bean>
</array>
</property>
</bean>
【讨论】:
这个问题应该被标记为一个正确的解决方案 :-) 谢谢【参考方案8】:我用过这个:
@RequestMapping(..)
@ResponseBody
public JsonNode myGetRequest()
...
//rawJsonString is the raw Json that we want to proxy back to the client
return objectMapper.readTree(rawJsonString);
Jackson 转换器知道如何将 JsonNode 转换为普通 Json。
【讨论】:
看起来你解析 rawJsonString 然后返回将再次转换为 json 的对象。不是一个很好的解决方案... 非常感谢,这确实帮助我避免返回带有转义字符的 JsonObject!【参考方案9】:\"
表示字符 "
正在被转义,这是标准的。如果它是这样打印的,那么您可能正在对对象进行双重序列化。
【讨论】:
是的,双重序列化可以解决这个问题。但是在哪里?以上是关于在spring mvc @ResponseBody中返回文字JSON字符串的主要内容,如果未能解决你的问题,请参考以下文章
解决spring-mvc @responseBody注解返回json 乱码问题
谁在 Spring MVC (@ResponseBody) 中设置响应内容类型
Spring MVC 3:通过 @ResponseBody 返回 XML
在 Spring MVC 中,如何在使用 @ResponseBody 时设置 mime 类型标头