问题描述
我在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?
推荐答案
当你意识到没有特殊的 HandlerMethodReturnValueHandler
用于新的JSR 353 API。相反,在这种情况下, 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,object)是 Map
(特殊类型), ObjectMapper
将地图的条目序列化为JSON键值对元素,其中Map键是JSON键,Map值是JSON值。对于密钥,它工作正常,序列化为名称
,年龄
,已结婚
。对于该值,它使用我上面提到的类和它们各自的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"}
这同样适用于其他字段。
The same applies for the other fields.
如果你想要正确编写JSON,只需返回字符串
。
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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!