Cómo devolver un objeto JSON desde un HashMap con Moxy y Jersey

Estoy usando Jersey 2.17 con Moxy y tengo funciones como:

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

User.preferences es un HashMap .

Funciona bien para casi todos los objetos a excepción de un HashMap que se traduce en:

“preferencias”: {“entrada”: [{“clave”: {“tipo”: “cadena”, “valor”: “idioma”}, “valor”: {“tipo”: “cadena”, “valor”: “en”}}, {“clave”: {“tipo”: “cadena”, “valor”: “país”}, “valor”: {“tipo”: “cadena”, “valor”: “EE. UU.”} }]}

pero lo que realmente me gustaría devolver es solo un objeto javascript como:

preferencias: {“idioma”: “en”, “país”: “EE. UU.”}

¿Cómo puedo hacer eso?

Sí MOXy y Maps no funcionan bien. Es triste, ya que JSON no es más que pares de clave / valor mapeados. Si desea usar MOXy, deberá usar un XmlAdapter . En cuyo caso, de la manera que desee el JSON, tendrá que crear un tipo (clase) que tenga el nombre de todas las preferencias posibles. Los pares de valores clave arbitrarios deben estar en la forma que requiera, pero como MOXy no puede hacer mapas, necesitará asignarlos a su propio tipo. Por ejemplo

 public class PreferencesAdapter extends XmlAdapter> { @XmlRootElement public static class Preference { public String language; public String country; } @Override public HashMap unmarshal(Preference p) throws Exception { HashMap map = new HashMap<>(); map.put("language", p.language); map.put("country", p.country); return map; } @Override public Preference marshal(HashMap v) throws Exception { Preference p = new Preference(); p.language = v.get("language"); p.country = v.get("country"); return p; } } 

Tu DTO

 @XmlRootElement public class User { @XmlJavaTypeAdapter(PreferencesAdapter.class) public HashMap preferences; } 

Pero si estamos haciendo todo esto, ¿por qué no utilizamos un objeto de Preferences en primer lugar en lugar de un Map ? Esa fue una pregunta retorica. Entiendo totalmente por qué no lo harías. Pero esta es una de las limitaciones de MOXy, ya que nos saca de quicio a JAXB, y JAXB nunca ha jugado bien con Map, lo cual es triste, como dije, JSON no es más que un Mapa de valores clave .

Por esta razón, y en realidad muchas otras que he encontrado en el pasado, no recomiendo usar MOXy aunque lo recomiende Jersey. En cambio, usa Jackson. Jackson ha sido de facto Java goto para el procesamiento JSON por un tiempo. Para Jackson, solo usa esta dependencia

  org.glassfish.jersey.media jersey-media-json-jackson ${jersey.version}  

Si elimina la dependencia de MOXy, este módulo de Jackson debería funcionar. De lo contrario, si abandona la dependencia de MOXy, deberá registrar el JacksonFeature