问题描述
我在 SpringMVC 项目中为 JSON 使用新的 Java API (JSR 353).
I am using the new Java API (JSR 353) for JSON in a SpringMVC project.
这个想法是生成一些 Json 数据并将其返回给客户端.我的控制器看起来有点像这样:
The idea is to generate some piece of Json data and have it returned to the client. The controller I have look somewhat like this:
@RequestMapping("/test")
@ResponseBody
public JsonObject test() {
JsonObject result = Json.createObjectBuilder()
.add("name", "Dade")
.add("age", 23)
.add("married", false)
.build();
return result;
}
当我访问它时,我得到的不是预期的 JSON 表示,而是这些:
And when I access this, instead of getting the expected representation of the JSON, I get these instead:
{"name":{"chars":"Dade","string":"Dade","valueType":"STRING"},"age":{"valueType":"NUMBER","integral":true},"married":{"valueType":"FALSE"}}
这是为什么?到底是怎么回事?以及如何让它正确返回预期的 JSON?
Why is this? What is going on? And how do I make it returned the expected JSON properly?
推荐答案
当您意识到新的 JSR 353 API 没有特殊的 HandlerMethodReturnValueHandler
时,答案很简单.相反,在这种情况下,RequestResponseBodyMethodProcessor
(用于 @ResponseBody
)使用 MappingJackson2HttpMessageConverter
来序列化处理程序方法的返回值.
The answer is pretty simple when you realize there is no special HandlerMethodReturnValueHandler
for the new JSR 353 API. Instead, in this case, the RequestResponseBodyMethodProcessor
(for @ResponseBody
) uses a MappingJackson2HttpMessageConverter
to serialize the return value of your handler method.
在内部,MappingJackson2HttpMessageConverter
使用 ObjectMapper
.默认情况下,ObjectMapper
使用类的 getter 将对象序列化为 JSON.
Internally, the MappingJackson2HttpMessageConverter
uses an ObjectMapper
. By default, the ObjectMapper
uses the getters of a class to serialize an object to JSON.
假设您正在使用 Glassfish
的 JSR 353 提供程序实现,这些类是 org.glassfish.json.JsonObjectBuilderImpl$JsonObjectImpl
、org.glassfish.json.JsonStringImpl
,和org.glassfish.json.JsonNumberImpl
和 javax.json.JsonValue$3
(值 FALSE
的匿名类).
Assuming you are using Glassfish
's provider implementation of the JSR 353, those classes are org.glassfish.json.JsonObjectBuilderImpl$JsonObjectImpl
, org.glassfish.json.JsonStringImpl
, and org.glassfish.json.JsonNumberImpl
, and javax.json.JsonValue$3
(an anonymous class for the value FALSE
).
因为 JsonObjectImpl
(你的结果,即 root,对象)是一个 Map
(特殊类型),ObjectMapper
将地图的条目序列化为JSON 键值对元素,其中 Map 键为 JSON 键,Map 值为 JSON 值.对于密钥,它工作正常,序列化为 name
、age
和 married
.对于值,它使用我上面提到的类及其各自的 getter.例如,org.glassfish.json.JsonStringImpl
实现为
Because JsonObjectImpl
(your result, ie. root, object) is a Map
(special type), ObjectMapper
serializes the map's entries as JSON key-value pair elements, where the Map key is the JSON key, and the Map value is the JSON value. For the key, it works fine, serializing as name
, age
, and married
. For the value, it uses the classes I mentioned above and their respective getters. For example, org.glassfish.json.JsonStringImpl
is implemented as
final class JsonStringImpl implements JsonString {
private final String value;
public JsonStringImpl(String value) {
this.value = value;
}
@Override
public String getString() {
return value;
}
@Override
public CharSequence getChars() {
return value;
}
@Override
public ValueType getValueType() {
return ValueType.STRING;
}
...
}
ObjectMapper
因此使用 Java Bean getter 序列化 JsonStringImpl
对象(即 Map Entry 的值),如
ObjectMapper
therefore uses the Java Bean getters to serialize the JsonStringImpl
object (that is the Map Entry's value), as
{"chars":"Dade","string":"Dade","valueType":"STRING"}
同样适用于其他领域.
如果您想正确编写 JSON,只需返回一个 String
.
If you want to correctly write the JSON, simply return a String
.
@RequestMapping("/test", produces="application/json")
@ResponseBody
public String test() {
JsonObject result = Json.createObjectBuilder()
.add("name", "Dade")
.add("age", 23)
.add("married", false)
.build();
return result.toString();
}
或者自己制作HandlerMethodReturnValueHandler
,稍微复杂一点,但更有收获.
Or make your own HandlerMethodReturnValueHandler
, a little more complicated, but more rewarding.
这篇关于在 SpringMVC 中使用 @ResponseBody 返回 JsonObject的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!