如何使用 Moxy 和 Jersey 从 HashMap return JSON 对象

How to return a JSON object from a HashMap with Moxy and Jersey

我正在将 Jersey 2.17 与 Moxy 一起使用,我的功能如下:

@Produces(APPLICATION_JSON)
@Restricted
public List<User> getFriends(
        @PathParam("user") String user
) {
    return userDAO.getFriends(user);
}

User.preferences 是 HashMap.

它适用于几乎所有对象,除了 HashMap 被翻译成:

"preferences":{"entry":[{"key":{"type":"string","value":"language"},"value":{"type":"string","value":"en"}},{"key":{"type":"string","value":"country"},"value":{"type":"string","value":"US"}}]}

但我真正想要 return 的只是一个 javascript 对象,例如:

preferences:{"language":"en","country":"US"}

我该怎么做?

是的,MOXy 和地图运行不佳。很遗憾,因为 JSON 只不过是映射的 key/value 对。如果要使用 MOXy,则需要使用 XmlAdapter。在这种情况下,按照您想要 JSON 的方式,您将需要创建一个具有所有可能首选项名称的类型 (class)。任意键值对 应该 是您需要的形式,但由于 MOXy 不能做映射,您需要将其映射到您自己的类型。例如

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 实际上只不过是一个键值映射。

出于这个原因,以及实际上我过去遇到的许多其他原因,我不推荐使用 MOXy,即使它是 Jersey 推荐的。相反,使用杰克逊。一段时间以来,Jackson 一直是 JSON 处理的事实上的 Java goto。对于 Jackson,只需使用此依赖项

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-jackson</artifactId>
    <version>${jersey.version}</version>
</dependency>

如果去掉 MOXy 依赖项,这个 Jackson 模块应该可以正常工作。否则,如果您离开 MOXy 依赖项,则需要注册 JacksonFeature