====== 10.2 JSON ====== Por ahora hemos usado JSON desde la parte cliente. La parte positiva ha sido que no hemos tenido que saber nada de JSON ya que AngularJS se ha encargado de todo. Desde Java también se podríamos olvidarnos de JSON y hacer que Spring se encargara de todo pero en vez de hacer eso he decidido un enfoque en el que seamos nosotros los que nos encarguemos de cierta parte de JSON. El motivo de ello es entender mejor como funciona todo. En una aplicación real se debería mirar todas las funcionalidades de Spring para evitar tener que tratar con JSON o al menor hacerlo lo menos posible. Lo primero que tenemos que aprender es como transformar un String en formato JSON a un objeto Java y como transformar un objeto Java en un String JSON. Para ayudarnos en esta tarea hay varias librerías Java siendo las 2 mas famosas: * [[http://wiki.fasterxml.com/JacksonHome|Jackson]] * [[https://code.google.com/p/google-gson/|gson]] De las 2 usaremos Jackson ya que lleva mas tiempo y tiene muchas mas funcionalidades. Lo malo de Jackson es que cuando empiezas a leer la documentación uno se pierde con todo lo que ofrece pero cuando estás en un proyecto real , acabas agradeciendo todo lo que ofrece. Así que en este tema solo vamos a ver lo básico de usar Jackson y como encapsularlo tras un interfaz para abstraernos de los detalle y por si en un futuro quisiéramos cambiar de librería. ===== Instalacion ===== Para usar Jackson es necesario descargar los jars de las siguientes páginas: * [[http://repo2.maven.org/maven2/com/fasterxml/jackson/core/jackson-annotations]] * [[http://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-core]] * [[http://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-databind]] Los ejemplos de este curso han sido hecho con la versión 2.4 y los enlaces directos son: * [[http://repo2.maven.org/maven2/com/fasterxml/jackson/core/jackson-annotations/2.4.2/jackson-annotations-2.4.2.jar|jackson-annotations-2.4.2.jar]] * [[http://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-core/2.4.2/jackson-core-2.4.2.jar|jackson-core-2.4.2.jar]] * [[http://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-databind/2.4.2/jackson-databind-2.4.2.jar|jackson-databind-2.4.2.jar]] Una vez descargados simplemente habrá que : * Crear una nueva carpeta llamada ''lib'' en la raiz del proyecto * Copiar los jars a la nueva carpeta ''lib'' * Añadir los 3 jars al proyecto usando rutas relativas. ===== Uso de Jackson ===== La clase principal de Jackson es ''ObjectMapper'' Se usan principalmente 2 métodos: * ''readValue'' : Transforma un String en formato JSON en un objeto Java. Por desgracia un String JSON no indica la clase a la que pertenece por lo que es necesario indicarsela. * ''writeValueAsString'' : Transforma un objeto Java en un String JSON Veamos un ejemplo de transformar un objeto Java de la clase ''Usuario'' en un String JSON: ObjectMapper objectMapper = new ObjectMapper(); String jsonUsuario=objectMapper.writeValueAsString(usuario); * Línea 1: Creamos el objeto principal de Jackson llamado ''ObjectMapper'' * Línea 3: Transformamos el objeto de la clase Usuario al String en formato JSON mediante el método ''writeValueAsString''. Veamos un ejemplo de transformar un String JSON en un objeto Java de la clase ''Usuario'': ObjectMapper objectMapper = new ObjectMapper(); Usuario usuario=(Usuario)objectMapper.readValue(jsonUsuario, Usuario.class); * Línea 1: Creamos el objeto principal de Jackson llamado ''ObjectMapper'' * Línea 3: Transformamos el String en formato JSON al objeto de la clase ''Usuario'' mediante el método ''readValue''.Lo único a tener en cuenta es que necesitamos decirle a Jackson la clase Java del objeto a crear ya que en el String Jackson no aparece. Por ello le pasamos como segundo argumento ''Usuario.class''. Como vemos usar lo básico de Jackson es muy sencillo. ===== Encapsular Jackson===== Ahora vamos a encapsular el uso de Jackson para poder abstraernos de los detalle de usarlo y para poder cambiar la librería de Jackson por otra si fuera necesario. Creamos un interfaz llamado ''JsonTransformer''. class JsonTransformer <> JsonTransformer : String toJson (Object data) JsonTransformer : Object fromJson(String json,Class clazz) Por supuesto , este interfaz es muy sencillo , actualmente Java EE 7 ya dispone de [[https://json-processing-spec.java.net/|Java API for JSON Processing (JSON-P)]] El código Java es el siguiente: package es.cursoangularjs.jackson; public interface JsonTransformer { String toJson(Object data); Object fromJson(String json, Class clazz); } La forma mas correcta de definir el interfaz ''JsonTransformer'' es usando Generics en el método ''fromJSON'' y de esa forma ahorrarnos el cast ya que el tipo retornado en ''fromJSON'' siempre será el mismo que el de la clase que se le pasa como argumento en "clazz" public interface JsonTransformer { String toJson(Object data); T fromJSON(String json, Class clazz) } Aunque no lo uso en el resto del curso por no liar mas aun el curso. Creamos una implementación para este interfaz usando las librerías de Jackson llamado ''JsonTransformerImplJackson''. class JsonTransformer <> JsonTransformer : String toJson(Object data) JsonTransformer : Object fromJson(String json,Class clazz) class JsonTransformerImplJackson JsonTransformer <.. JsonTransformerImplJackson El código Java es el siguiente: package es.cursoangularjs.jackson; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; public class JsonTransformerImplJackson implements JsonTransformer { @Override public String toJson(Object data) { try { ObjectMapper objectMapper = new ObjectMapper(); return objectMapper.writeValueAsString(data); } catch (JsonProcessingException ex) { throw new RuntimeException(ex); } } @Override public Object fromJson(String json, Class clazz) { try { ObjectMapper objectMapper = new ObjectMapper(); return objectMapper.readValue(json, clazz); } catch (IOException ex) { throw new RuntimeException(ex); } } } ===== Ejemplo ===== Ahora veamos un simple ejemplo que usa transforma un objeto ''Usuario'' a un String JSON y dicho String se vuelve a transformar a un objeto ''Usuario''. public class Main { public static void main(String[] args) { JsonTransformer jsonTransformer=new JsonTransformerImplJackson(); Usuario usuario=new Usuario("Alberto Tortosa","alberto_tortosa@gmail.com",91); String jsonUsuario=jsonTransformer.toJson(usuario); System.out.println(jsonUsuario); Usuario newUsuario=(Usuario) jsonTransformer.fromJson(jsonUsuario, Usuario.class); System.out.println("Nombre:"+newUsuario.getNombre()); System.out.println("E-Mail:"+newUsuario.getEmail()); System.out.println("Edad:"+newUsuario.getEdad()); } } El resultado por pantalla es: {"nombre":"Alberto Tortosa","email":"alberto_tortosa@gmail.com","edad":91} Nombre:Alberto Tortosa E-Mail:alberto_tortosa@gmail.com Edad:91 Este ejemplo se encuentra en git en [[https://github.com/logongas/cursoangularjs/tree/master/jackson]] ===== Referencias ===== * [[http://wiki.fasterxml.com/JacksonHome|Jackson]]