如何使用 Moxy 和 Jersey 从 HashMap 返回 JSON 对象
我正在使用带有 Moxy 的 Jersey 2.17,并且我的功能如下:
I am using Jersey 2.17 with Moxy and I have functions like :
@Produces(APPLICATION_JSON)
@Restricted
public List<User> getFriends(
@PathParam("user") String user
) {
return userDAO.getFriends(user);
}
User.preferences 是一个 HashMap
.
User.preferences is a HashMap
.
它适用于几乎所有对象,除了被翻译成的 HashMap
:
It works fine for almost all Objects except for a HashMap
which gets translated into:
"preferences":{"entry":[{"key":{"type":"string","value":"language"},"value":{"type":"string","value":"en"}},{"key":{"type":"string","value":"country"},"value":{"type":"string","value":"美国"}}]}
"preferences":{"entry":[{"key":{"type":"string","value":"language"},"value":{"type":"string","value":"en"}},{"key":{"type":"string","value":"country"},"value":{"type":"string","value":"US"}}]}
但我真正想要返回的只是一个 javascript 对象,例如:
but what I would really like to return is just a javascript object like:
首选项:{"language":"en","country":"US"}
preferences:{"language":"en","country":"US"}
我该怎么做?
推荐答案
是的,MOXy 和地图无法正常工作.可悲的是,JSON 只不过是映射的键/值对.如果你想使用 MOXy,你需要使用 XmlAdapter
.在这种情况下,您需要 JSON 的方式,您需要创建一个类型(类),它具有所有可能的首选项的名称.任意键值对应该采用您需要的形式,但由于 MOXy 无法进行映射,您需要将其映射到您自己的类型.比如
Yeah MOXy and Maps don't work well. It's sad, as JSON is nothing more than mapped key/value pairs. If you want to use MOXy, you will need to use an XmlAdapter
. In which case, the way you want the JSON, you will need to create a type (class) that has the name of all possible preferences. Arbitrary key value pairs should be in the form you require, but since MOXy can't do maps, you'll need to map it to your own type. For instance
public class PreferencesAdapter extends XmlAdapter<Preference, HashMap<String, String>> {
@XmlRootElement
public static class Preference {
public String language;
public String country;
}
@Override
public HashMap<String, String> unmarshal(Preference p) throws Exception {
HashMap<String, String> map = new HashMap<>();
map.put("language", p.language);
map.put("country", p.country);
return map;
}
@Override
public Preference marshal(HashMap<String, String> v) throws Exception {
Preference p = new Preference();
p.language = v.get("language");
p.country = v.get("country");
return p;
}
}
你的 DTO
@XmlRootElement
public class User {
@XmlJavaTypeAdapter(PreferencesAdapter.class)
public HashMap<String, String> preferences;
}
但是,如果我们要做这一切,为什么不首先使用 Preferences
对象而不是 Map
?那是一个反问.我完全理解你为什么不这样做.但这是 MOXy 的限制之一,因为它让我们在引擎盖下对 JAXB 感到沉重,而 JAXB 从来没有很好地与 Map 配合使用,这很可悲,就像我说的那样,JSON 真的只不过是一个键值的 Map.
But if we're doing to do all this, why don't we just use a Preferences
object in the first place instead of a Map
? That was a rhetorical question. I totally understand why you wouldn't. But this is one of the limitations of MOXy, as it makes heavy us of JAXB under the hood, and JAXB has never played nicely with Map, which is sad, as like I said, JSON is really nothing more than a Map of key values.
出于这个原因,实际上我过去遇到过许多其他人,我不推荐使用 MOXy,即使它是 Jersey 推荐的.相反,使用杰克逊.一段时间以来,Jackson 一直是 JSON 处理的事实上的 Java goto.对于 Jackson,只需使用此依赖项
For this reason, and actually many others I have encountered in the past, I do no recommend using MOXy even though it is recommended by Jersey. Instead, use Jackson. Jackson has been the defacto Java goto for JSON processing for a while. For Jackson, just use this dependency
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>${jersey.version}</version>
</dependency>
如果你去掉 MOXy 依赖,这个 Jackson 模块应该可以解决问题.否则,如果您离开 MOXy 依赖项,则需要注册 JacksonFeature
If you take out the MOXy dependency, this Jackson module should work out the box. Otherwise if you leave the MOXy dependency, you will need to register the JacksonFeature
相关文章