我将数据库中的对象存储为JSON字符串。我想制作一个暴露这些字符串的REST服务。然而,当我编写我的方法时,我回来的字符串会引用它们的引号。例如,我已经包含了一个返回String的方法,
@RequestMapping(value = "test", method = RequestMethod.GET)
public @ResponseBody
String getTest() {
return "{\"a\":1, \"b\":\"foo\"}";
}
但是当我在浏览器中调用此方法时,我得到一个回复" {\" a \":1,\" b \":\&# 34; FOO \"}"当我真正想要发生的是{" a":1," b":" foo"}。我认为" String"因为返回类型可能是问题,但我还能做什么?包装器类做同样的事情:
{
"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;
}
由于
编辑:如下所示,似乎字符串是双重编码的。在我的配置中注释掉这两个类可以解决这个问题。但是,我仍然有其他地方我想要返回对象,并希望保持那些运行通过我知道在哪里配置的常见序列化bean。所以我看到我的选择: a)自己完成序列化。所有方法都返回字符串,那些已经是JSON的方法返回自己,而那些作为对象的方法都返回JSONUtil.toJson(object)。我不喜欢这种方法,但我知道它会起作用。 b)使用类似于以下内容的包装类:
public static class Wrapper {
@JsonRawValue
private final String value;
}
这导致了一个尴尬的价值&#34;在前面虽然没有实际意义。
基本上我想要的是@JsonRawValue,但让它在RequestMapping方法而不是属性上工作。 思考?意见?其他建议?
答案 0 :(得分:43)
这适用于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() {
// ...
}
HTH, 的Jukka
答案 1 :(得分:25)
我想您想要的是生成内容类型为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-config:
@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-config:
<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>
答案 2 :(得分:11)
我用过这个:
@RequestMapping(..)
@ResponseBody
public JsonNode myGetRequest(){
...
//rawJsonString is the raw Json that we want to proxy back to the client
return objectMapper.readTree(rawJsonString);
}
杰克逊转换器知道如何将JsonNode转换为普通的Json。
答案 3 :(得分:4)
如果要在浏览器中将JSON String转换为JSON对象,请在Jackson convertor之前保留字符串转换器 请按照此link获取完整示例。它适用于自定义转换器配置和弹簧验证。
converters.add(stringConverter());
converters.add(mappingJackson2HttpMessageConverter());
super.configureMessageConverters(converters);
converters.add(mappingJackson2HttpMessageConverter());
converters.add(stringConverter());
super.configureMessageConverters(converters);
答案 4 :(得分:1)
\"
表示正在转义字符"
,这是标准的。如果它是这样打印的,你可能会对对象进行双重序列化。
答案 5 :(得分:1)
在我的情况下,我希望响应类型由请求参数确定,因此必须在代码中指定内容类型,例如:
@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 :(得分:1)
今天我们遇到了同样的问题,并用多个转换器解决了这个问题。现在每个String
都会被视为一个字符串,而其他Object
将被杰克逊序列化。这允许在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;
}
答案 7 :(得分:0)
我知道这是一个老问题,但我只是在处理相反的问题(我正在返回一个字符串并希望它转换为JSON)。在您的情况下,听起来您只是想将您的String视为纯字符串,并且没有对其进行任何类型的JSON转换,因为您已经拥有JSON。
因此,在您的情况下,如果您现在使用的是Jackson2,则不想使用MappingJacksonHttpMessageConverter
(或MappingJackson2HttpMessageConverter
)。您根本不需要完成任何转换,并且该转换器将Java对象转换为JSON或从JSON转换。所以你应该只使用普通的StringHttpMessageConverter
。你可以通过改变你的设置方法来做到这一点:
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new StringHttpMessageConverter());
}
此转换器适用于*/*
类型(文档不正确,显示text/*
,我在调试器中找到了困难的方法)。因此,无论您的内容类型是否为application/json
,如果您使用此转换器,Spring将不会使您的字符串混乱。
答案 8 :(得分:0)
解决您的问题的方法是,无需更改任何配置即可完美运行
import com.fasterxml.jackson.databind.JsonNode;
import com.github.fge.jackson.JsonLoader;
JsonNode getTest() {
return JsonLoader.fromString("{\"a\":1, \"b\":\"foo\"}");
}