Tutorial de ejemplo de la API del analizador de Java JSON de Jackson

El analizador de Java JSON de Jackson es muy popular y también se utiliza en el marco Spring. La API de procesamiento de JSON de Java no es muy fácil de usar y no ofrece funciones para la transformación automática de JSON a objetos Java y viceversa. Afortunadamente, tenemos algunas API alternativas que podemos usar para el procesamiento de JSON. En el último artículo, aprendimos sobre la API de Google Gson y vimos lo fácil que es usarla.

Analizador de Java JSON de Jackson

Para usar la API Java JSON de Jackson en nuestro proyecto, podemos agregarla a la ruta de compilación del proyecto o, si está usando maven, podemos agregar la siguiente dependencia.

dependencygroupIdcom.fasterxml.jackson.core/groupIdartifactIdjackson-databind/artifactIdversion2.2.3/version/dependency

El jar de jackson-databind depende de las bibliotecas jackson-core y jackson-annotations , por lo que si las agrega directamente a la ruta de compilación, asegúrese de agregar las tres; de lo contrario, obtendrá un error de tiempo de ejecución. La API del analizador JSON de Jackson proporciona una manera sencilla de convertir JSON en un objeto POJO y admite una conversión sencilla a un mapa a partir de datos JSON. Jackson también admite genéricos y los convierte directamente de JSON a objeto.

Ejemplo de JSON de Jackson

Para nuestro ejemplo de conversión de JSON a POJO/objeto Java, tomaremos un ejemplo complejo con objetos anidados y matrices. Usaremos matrices, listas y mapas en objetos Java para la conversión. Nuestro JSON complejo se almacena en un archivo employee.txt con la siguiente estructura:

{  "id": 123,  "name": "Pankaj",  "permanent": true,  "address": {    "street": "Albany Dr",    "city": "San Jose",    "zipcode": 95129  },  "phoneNumbers": [    123456,    987654  ],  "role": "Manager",  "cities": [    "Los Angeles",    "New York"  ],  "properties": {    "age": "29 years",    "salary": "1000 USD"  }}

Tenemos las siguientes clases Java correspondientes a los datos json.

package com.journaldev.jackson.model;public class Address {private String street;private String city;private int zipcode;public String getStreet() {return street;}public void setStreet(String street) {this.street = street;}public String getCity() {return city;}public void setCity(String city) {this.city = city;}public int getZipcode() {return zipcode;}public void setZipcode(int zipcode) {this.zipcode = zipcode;}@Overridepublic String toString(){return getStreet() + ", "+getCity()+", "+getZipcode();}}

La clase de dirección corresponde al objeto interno en los datos json raíz.

package com.journaldev.jackson.model;import java.util.Arrays;import java.util.List;import java.util.Map;public class Employee {private int id;private String name;private boolean permanent;private Address address;private long[] phoneNumbers;private String role;private ListString cities;private MapString, String properties;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public boolean isPermanent() {return permanent;}public void setPermanent(boolean permanent) {this.permanent = permanent;}public Address getAddress() {return address;}public void setAddress(Address address) {this.address = address;}public long[] getPhoneNumbers() {return phoneNumbers;}public void setPhoneNumbers(long[] phoneNumbers) {this.phoneNumbers = phoneNumbers;}public String getRole() {return role;}public void setRole(String role) {this.role = role;}@Overridepublic String toString(){StringBuilder sb = new StringBuilder();sb.append("***** Employee Details *****n");sb.append("ID="+getId()+"n");sb.append("Name="+getName()+"n");sb.append("Permanent="+isPermanent()+"n");sb.append("Role="+getRole()+"n");sb.append("Phone Numbers="+Arrays.toString(getPhoneNumbers())+"n");sb.append("Address="+getAddress()+"n");sb.append("Cities="+Arrays.toString(getCities().toArray())+"n");sb.append("Properties="+getProperties()+"n");sb.append("*****************************");return sb.toString();}public ListString getCities() {return cities;}public void setCities(ListString cities) {this.cities = cities;}public MapString, String getProperties() {return properties;}public void setProperties(MapString, String properties) {this.properties = properties;}}

Employee es el bean de Java que representa el objeto JSON raíz. Ahora veamos cómo podemos transformar JSON en un objeto Java utilizando la API del analizador JSON de Jackson.

package com.journaldev.jackson.json;import java.io.File;import java.io.IOException;import java.io.StringWriter;import java.nio.file.Files;import java.nio.file.Paths;import java.util.ArrayList;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.Map;import com.fasterxml.jackson.core.type.TypeReference;import com.fasterxml.jackson.databind.JsonNode;import com.fasterxml.jackson.databind.ObjectMapper;import com.fasterxml.jackson.databind.SerializationFeature;import com.fasterxml.jackson.databind.node.ObjectNode;import com.journaldev.jackson.model.Address;import com.journaldev.jackson.model.Employee;public class JacksonObjectMapperExample {public static void main(String[] args) throws IOException {//read json file data to Stringbyte[] jsonData = Files.readAllBytes(Paths.get("employee.txt"));//create ObjectMapper instanceObjectMapper objectMapper = new ObjectMapper();//convert json string to objectEmployee emp = objectMapper.readValue(jsonData, Employee.class);System.out.println("Employee Objectn"+emp);//convert Object to json stringEmployee emp1 = createEmployee();//configure Object mapper for pretty printobjectMapper.configure(SerializationFeature.INDENT_OUTPUT, true);//writing to console, can write to any output stream such as fileStringWriter stringEmp = new StringWriter();objectMapper.writeValue(stringEmp, emp1);System.out.println("Employee JSON isn"+stringEmp);}public static Employee createEmployee() {Employee emp = new Employee();emp.setId(100);emp.setName("David");emp.setPermanent(false);emp.setPhoneNumbers(new long[] { 123456, 987654 });emp.setRole("Manager");Address add = new Address();add.setCity("Bangalore");add.setStreet("BTM 1st Stage");add.setZipcode(560100);emp.setAddress(add);ListString cities = new ArrayListString();cities.add("Los Angeles");cities.add("New York");emp.setCities(cities);MapString, String props = new HashMapString, String();props.put("salary", "1000 Rs");props.put("age", "28 years");emp.setProperties(props);return emp;}}

Cuando ejecutamos el programa anterior, obtendrá el siguiente resultado.

Employee Object***** Employee Details *****ID=123Name=PankajPermanent=trueRole=ManagerPhone Numbers=[123456, 987654]Address=Albany Dr, San Jose, 95129Cities=[Los Angeles, New York]Properties={age=29 years, salary=1000 USD}*****************************Employee JSON is//printing same as above json file data

com.fasterxml.jackson.databind.ObjectMapper es la clase más importante de la API de Jackson que proporciona los métodos readValue() y writeValue() para transformar JSON en un objeto Java y un objeto Java en JSON . La clase ObjectMapper se puede reutilizar y podemos inicializarla una vez como un objeto Singleton. Hay muchas versiones sobrecargadas de los métodos readValue() y writeValue() para trabajar con matrices de bytes, archivos, flujos de entrada/salida y objetos Reader/Writer.

Jackson JSON: conversión de JSON a mapa

A veces tenemos un objeto JSON como el que se muestra a continuación, en el archivo data.txt:

{  "name": "David",  "role": "Manager",  "city": "Los Angeles"}

Y queremos convertirlo en un mapa y no en un objeto Java con las mismas propiedades y claves. Podemos hacerlo muy fácilmente en la API JSON de Jackson con dos métodos con el código siguiente:

//converting json to Mapbyte[] mapData = Files.readAllBytes(Paths.get("data.txt"));MapString,String myMap = new HashMapString, String();ObjectMapper objectMapper = new ObjectMapper();myMap = objectMapper.readValue(mapData, HashMap.class);System.out.println("Map is: "+myMap);//another waymyMap = objectMapper.readValue(mapData, new TypeReferenceHashMapString,String() {});System.out.println("Map using TypeReference: "+myMap);

Una vez que ejecutamos el fragmento anterior, obtenemos el siguiente resultado:

Map is: {name=David, role=Manager, city=Los Angeles}Map using TypeReference: {name=David, role=Manager, city=Los Angeles}

Jackson JSON: lectura de una clave JSON específica

A veces tenemos datos json y nos interesan solo algunos de los valores clave, por lo que en ese caso convertir todo el JSON en un objeto no es una buena idea. La API JSON de Jackson ofrece la opción de leer datos json como un árbol como el analizador DOM y podemos leer elementos específicos del objeto JSON a través de esto. El código a continuación proporciona un fragmento para leer entradas específicas del archivo json.

//read json file data to Stringbyte[] jsonData = Files.readAllBytes(Paths.get("employee.txt"));//create ObjectMapper instanceObjectMapper objectMapper = new ObjectMapper();//read JSON like DOM ParserJsonNode rootNode = objectMapper.readTree(jsonData);JsonNode idNode = rootNode.path("id");System.out.println("id = "+idNode.asInt());JsonNode phoneNosNode = rootNode.path("phoneNumbers");IteratorJsonNode elements = phoneNosNode.elements();while(elements.hasNext()){JsonNode phone = elements.next();System.out.println("Phone No = "+phone.asLong());}

Obtenemos el siguiente resultado cuando ejecutamos el fragmento de código anterior.

id = 123Phone No = 123456Phone No = 987654

Jackson JSON – Editar documento JSON

La API de Java de Jackson JSON proporciona métodos útiles para agregar, editar y eliminar claves de datos JSON y luego podemos guardarlos como un nuevo archivo JSON o escribirlos en cualquier secuencia. El código a continuación nos muestra cómo hacer esto fácilmente.

byte[] jsonData = Files.readAllBytes(Paths.get("employee.txt"));ObjectMapper objectMapper = new ObjectMapper();//create JsonNodeJsonNode rootNode = objectMapper.readTree(jsonData);//update JSON data((ObjectNode) rootNode).put("id", 500);//add new key value((ObjectNode) rootNode).put("test", "test value");//remove existing key((ObjectNode) rootNode).remove("role");((ObjectNode) rootNode).remove("properties");objectMapper.writeValue(new File("updated_emp.txt"), rootNode);

Si ejecuta el código anterior y busca el nuevo archivo, notará que no tiene las claves “role” y “properties”. También notará que el valor “id” se actualiza a 500 y se agrega una nueva clave “test” al archivo updated_emp.txt.

Ejemplo de API de transmisión JSON de Jackson

La API de Java de Jackson JSON también proporciona compatibilidad con streaming, lo que resulta útil para trabajar con datos json de gran tamaño, ya que lee todo el archivo como tokens y utiliza menos memoria. El único problema con la API de streaming es que debemos ocuparnos de todos los tokens mientras analizamos los datos JSON. Si tenemos datos json como {“role”:“Manager”}, obtendremos los siguientes tokens en orden: { (objeto de inicio), “role” (nombre de clave), “Manager” (valor de clave) y } (objeto final). Los dos puntos (:) son el delimitador en JSON y, por lo tanto, no se consideran un token.

package com.journaldev.jackson.json;import java.io.File;import java.io.IOException;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import com.fasterxml.jackson.core.JsonFactory;import com.fasterxml.jackson.core.JsonParseException;import com.fasterxml.jackson.core.JsonParser;import com.fasterxml.jackson.core.JsonToken;import com.journaldev.jackson.model.Address;import com.journaldev.jackson.model.Employee;public class JacksonStreamingReadExample {public static void main(String[] args) throws JsonParseException, IOException {//create JsonParser objectJsonParser jsonParser = new JsonFactory().createParser(new File("employee.txt"));//loop through the tokensEmployee emp = new Employee();Address address = new Address();emp.setAddress(address);emp.setCities(new ArrayListString());emp.setProperties(new HashMapString, String());ListLong phoneNums = new ArrayListLong();boolean insidePropertiesObj=false;parseJSON(jsonParser, emp, phoneNums, insidePropertiesObj);long[] nums = new long[phoneNums.size()];int index = 0;for(Long l :phoneNums){nums[index++] = l;}emp.setPhoneNumbers(nums);jsonParser.close();//print employee objectSystem.out.println("Employee Objectnn"+emp);}private static void parseJSON(JsonParser jsonParser, Employee emp,ListLong phoneNums, boolean insidePropertiesObj) throws JsonParseException, IOException {//loop through the JsonTokenswhile(jsonParser.nextToken() != JsonToken.END_OBJECT){String name = jsonParser.getCurrentName();if("id".equals(name)){jsonParser.nextToken();emp.setId(jsonParser.getIntValue());}else if("name".equals(name)){jsonParser.nextToken();emp.setName(jsonParser.getText());}else if("permanent".equals(name)){jsonParser.nextToken();emp.setPermanent(jsonParser.getBooleanValue());}else if("address".equals(name)){jsonParser.nextToken();//nested object, recursive callparseJSON(jsonParser, emp, phoneNums, insidePropertiesObj);}else if("street".equals(name)){jsonParser.nextToken();emp.getAddress().setStreet(jsonParser.getText());}else if("city".equals(name)){jsonParser.nextToken();emp.getAddress().setCity(jsonParser.getText());}else if("zipcode".equals(name)){jsonParser.nextToken();emp.getAddress().setZipcode(jsonParser.getIntValue());}else if("phoneNumbers".equals(name)){jsonParser.nextToken();while (jsonParser.nextToken() != JsonToken.END_ARRAY) {phoneNums.add(jsonParser.getLongValue());}}else if("role".equals(name)){jsonParser.nextToken();emp.setRole(jsonParser.getText());}else if("cities".equals(name)){jsonParser.nextToken();while (jsonParser.nextToken() != JsonToken.END_ARRAY) {emp.getCities().add(jsonParser.getText());}}else if("properties".equals(name)){jsonParser.nextToken();while(jsonParser.nextToken() != JsonToken.END_OBJECT){String key = jsonParser.getCurrentName();jsonParser.nextToken();String value = jsonParser.getText();emp.getProperties().put(key, value);}}}}}

JsonParser es la API de transmisión de JSON de Jackson para leer datos JSON. La usamos para leer datos del archivo y luego se usa el método parseJSON() para recorrer los tokens y procesarlos para crear nuestro objeto Java. Observe que el método parseJSON() se llama de forma recursiva para “dirección” porque es un objeto anidado en los datos JSON. Para analizar matrices, estamos recorriendo el documento JSON. Podemos usar la clase JsonGenerator para generar datos JSON con la API de transmisión.

package com.journaldev.jackson.json;import java.io.FileOutputStream;import java.io.IOException;import java.util.Set;import com.fasterxml.jackson.core.JsonFactory;import com.fasterxml.jackson.core.JsonGenerator;import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;import com.journaldev.jackson.model.Employee;public class JacksonStreamingWriteExample {public static void main(String[] args) throws IOException {Employee emp = JacksonObjectMapperExample.createEmployee();JsonGenerator jsonGenerator = new JsonFactory().createGenerator(new FileOutputStream("stream_emp.txt"));//for pretty printingjsonGenerator.setPrettyPrinter(new DefaultPrettyPrinter());jsonGenerator.writeStartObject(); // start root objectjsonGenerator.writeNumberField("id", emp.getId());jsonGenerator.writeStringField("name", emp.getName());jsonGenerator.writeBooleanField("permanent", emp.isPermanent());jsonGenerator.writeObjectFieldStart("address"); //start address objectjsonGenerator.writeStringField("street", emp.getAddress().getStreet());jsonGenerator.writeStringField("city", emp.getAddress().getCity());jsonGenerator.writeNumberField("zipcode", emp.getAddress().getZipcode());jsonGenerator.writeEndObject(); //end address objectjsonGenerator.writeArrayFieldStart("phoneNumbers");for(long num : emp.getPhoneNumbers())jsonGenerator.writeNumber(num);jsonGenerator.writeEndArray();jsonGenerator.writeStringField("role", emp.getRole());jsonGenerator.writeArrayFieldStart("cities"); //start cities arrayfor(String city : emp.getCities())jsonGenerator.writeString(city);jsonGenerator.writeEndArray(); //closing cities arrayjsonGenerator.writeObjectFieldStart("properties");SetString keySet = emp.getProperties().keySet();for(String key : keySet){String value = emp.getProperties().get(key);jsonGenerator.writeStringField(key, value);}jsonGenerator.writeEndObject(); //closing propertiesjsonGenerator.writeEndObject(); //closing root objectjsonGenerator.flush();jsonGenerator.close();}}

JsonGenerator es fácil de usar en comparación con JsonParser. Eso es todo por el tutorial de referencia rápida de la API de Java de Jackson JSON Parser. La API de Java de Jackson JSON es fácil de usar y ofrece muchas opciones para facilitar el trabajo de los desarrolladores con datos JSON. Descargue el proyecto desde el siguiente enlace y juegue con él para explorar más opciones sobre la API de Jackson JSON.

Descargar el proyecto JSON de Jackson

Referencia: Página de GitHub de Jackson

SUSCRÍBETE A NUESTRO BOLETÍN 
No te pierdas de nuestro contenido ni de ninguna de nuestras guías para que puedas avanzar en los juegos que más te gustan.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Scroll al inicio