java - Cómo devolver un objeto JSON desde un HashMap con Moxy y Jersey
jersey-2.0 (1)
Sí, MOXy y Maps no funcionan bien.
Es triste, ya que JSON no es más que pares de clave / valor mapeados.
Si quiere usar MOXy, necesitará usar un
XmlAdapter
.
En cuyo caso, de la forma en que desea el JSON, deberá crear un tipo (clase) que tenga el nombre de todas las preferencias posibles.
Los pares de valores clave arbitrarios
deben
tener la forma que necesita, pero dado que MOXy no puede hacer mapas, deberá asignarlos a su propio tipo.
Por ejemplo
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;
}
}
Su DTO
@XmlRootElement
public class User {
@XmlJavaTypeAdapter(PreferencesAdapter.class)
public HashMap<String, String> preferences;
}
Pero si estamos haciendo todo esto, ¿por qué no usamos un objeto
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 da mucha importancia a JAXB, y JAXB nunca ha jugado bien con Map, lo cual es triste, como dije, JSON no es más que un Map de valores clave. .
Por esta razón, y en realidad muchas otras que he encontrado en el pasado, no recomiendo usar MOXy a pesar de que Jersey lo recomienda. En cambio, usa Jackson. Jackson ha sido el goto de facto de Java para el procesamiento JSON durante un tiempo. Para Jackson, solo usa esta dependencia
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>${jersey.version}</version>
</dependency>
Si elimina la dependencia de MOXy, este módulo Jackson debería funcionar de la caja.
De lo contrario, si abandona la dependencia MOXy, deberá registrar
JacksonFeature
Estoy usando Jersey 2.17 con Moxy y tengo funciones como:
@Produces(APPLICATION_JSON)
@Restricted
public List<User> getFriends(
@PathParam("user") String user
) {
return userDAO.getFriends(user);
}
User.preferences es un
HashMap
.
Funciona bien para casi todos los objetos, excepto para un
HashMap
que se traduce en:
"preferencias": {"entrada": [{"clave": {"tipo": "cadena", "valor": "idioma"}, "valor": {"tipo": "cadena", "valor": "en"}}, {"key": {"type": "string", "value": "country"}, "value": {"type": "string", "value": "US"} }]}
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?