Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
349 views
in Technique[技术] by (71.8m points)

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

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 is a 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":"US"}}]}

but what I would really like to return is just a javascript object like:

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

How can I do that?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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;
    }
}

Your DTO

@XmlRootElement
public class User {
    @XmlJavaTypeAdapter(PreferencesAdapter.class)
    public HashMap<String, String> preferences;
}

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.

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>

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...