Java JSON con Gson
Analiza y serializa JSON en Java con la biblioteca Gson de Google: toJson, fromJson y TypeToken.
JSON es la lengua franca de las APIs web modernas, y las aplicaciones Java constantemente necesitan convertir objetos en JSON y volver a parsear JSON en objetos. Gson es la biblioteca de código abierto de Google para exactamente esto: un kit de herramientas pequeño y sin dependencias que mapea objetos Java a texto JSON y viceversa con casi ningún código repetitivo. Este capítulo muestra cómo funciona Gson y los patrones que usarás a diario.
Si eres nuevo en el formato en sí, comienza con la introducción a JSON; para la biblioteca alternativa principal, consulta Java JSON con Jackson.
Agregar Gson a tu Proyecto
Gson no forma parte del JDK, por lo que debes añadirlo como dependencia. Con Maven lo declaras en tu pom.xml:
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.11.0</version>
</dependency>Con Gradle la misma dependencia es una sola línea:
implementation 'com.google.code.gson:gson:2.11.0'Todo lo que haces con Gson pasa por una única clase de punto de entrada, Gson. Normalmente creas una instancia y la reutilizas — es thread-safe y económica de compartir.
import com.google.gson.Gson;
Gson gson = new Gson();Serializar Objetos a JSON
Convertir un objeto Java en texto JSON se llama serialización, y Gson lo hace con toJson(). Le pasas cualquier objeto y Gson recorre sus campos usando reflexión, produciendo un string JSON. No se requieren anotaciones ni configuración para clases ordinarias.
class Book {
String title;
String author;
int year;
boolean inStock;
Book(String title, String author, int year, boolean inStock) {
this.title = title;
this.author = author;
this.year = year;
this.inStock = inStock;
}
}
Gson gson = new Gson();
Book b = new Book("Clean Code", "Robert Martin", 2008, true);
String json = gson.toJson(b);
// {"title":"Clean Code","author":"Robert Martin","year":2008,"inStock":true}Los nombres de los campos se convierten en claves JSON, y los tipos Java se mapean a los tipos JSON naturales: String a un string entre comillas, int/double a un número, boolean a true/false. Un campo null se omite por defecto.
Deserializar JSON a Objetos
La dirección inversa — deserialización — usa fromJson(). Pasas el texto JSON y la Class destino, y Gson crea una instancia y rellena los campos haciendo coincidir las claves JSON con los nombres de los campos.
String json = "{\"title\":\"Clean Code\",\"author\":\"Robert Martin\",\"year\":2008,\"inStock\":true}";
Gson gson = new Gson();
Book b = gson.fromJson(json, Book.class);
System.out.println(b.title); // Clean Code
System.out.println(b.year); // 2008Si una clave JSON no tiene campo coincidente, Gson la ignora; si un campo no tiene clave coincidente, se queda en su valor por defecto (null, 0 o false). Este comportamiento indulgente hace que Gson sea resistente cuando una API añade nuevos campos.
TypeToken para Colecciones Genéricas
Debido al borrado de tipos, Java descarta la información de tipo genérico en tiempo de ejecución, por lo que gson.fromJson(json, List.class) no puede saber que quieres una List<Book> — devolvería una List de objetos LinkedTreeMap. Gson resuelve esto con TypeToken, que captura el tipo genérico completo para que la deserialización produzca los elementos que esperas.
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.List;
String json = "[{\"title\":\"Effective Java\",\"year\":2018}]";
Type listType = new TypeToken<List<Book>>(){}.getType();
List<Book> books = gson.fromJson(json, listType);Usa un TypeToken siempre que el tipo destino involucre genéricos — List<T>, Map<K, V>, o combinaciones anidadas. Para clases simples sin genéricos, la forma simple Book.class es suficiente.
Pretty Printing y Configuración Personalizada
El Gson por defecto produce JSON compacto en una sola línea. Para configurar el comportamiento, construyes una instancia con GsonBuilder. La solicitud más común es el pretty printing — salida indentada y legible por humanos para registros y archivos de configuración.
import com.google.gson.GsonBuilder;
Gson gson = new GsonBuilder()
.setPrettyPrinting()
.serializeNulls() // include null fields instead of dropping them
.create();
System.out.println(gson.toJson(b));GsonBuilder controla muchos otros comportamientos. Algunos que encontrarás con frecuencia:
| Método del builder | Efecto |
|---|---|
setPrettyPrinting() | Salida indentada en múltiples líneas |
serializeNulls() | Emite campos null en lugar de omitirlos |
setDateFormat(...) | Controla cómo se formatean los valores Date |
registerTypeAdapter(...) | Conecta un serializador/deserializador personalizado para un tipo |
excludeFieldsWithoutExposeAnnotation() | Solo serializa campos marcados con @Expose |
Para control total sobre un tipo, registras un adaptador personalizado que implementa JsonSerializer y/o JsonDeserializer — útil cuando un campo necesita un formato especial que la reflexión no puede inferir.
Un Ejemplo Práctico: Serializar, Parsear y Round-Trip
Gson en sí no está en el classpath de este ejecutor, por lo que el programa a continuación demuestra los mismos conceptos usando solo el JDK: serializa un record a JSON manualmente, parsea el texto de vuelta en campos, reconstruye el objeto y confirma que el round-trip no tiene pérdidas. Esto es exactamente lo que gson.toJson() y gson.fromJson() automatizan por ti.
Qué extraer de la ejecución:
- La primera línea muestra la serialización: el record
Bookse convierte en{"title":"Clean Code","author":"Robert Martin","year":2008,"inStock":true}, donde cada campo es una clave JSON y los tipos se mapean a sus formas JSON naturales — exactamente lo que producegson.toJson(). - La segunda línea muestra la deserialización: parsear ese texto de vuelta y reconstruir un
Book, el mismo trabajo que hacegson.fromJson(json, Book.class)en una sola llamada. Round-trip equal? truedemuestra que la conversión no tiene pérdidas — serializar y luego deserializar produce un objeto igual al original, la propiedad que busca todo mapeador JSON.- La línea
Array JSONmuestra unaList<Book>renderizada como un array JSON de objetos, la estructura que deserializarías con unTypeToken<List<Book>>. - El bloque
Prettymuestra salida indentada en múltiples líneas, ilustrando lo que te daGsonBuilder.setPrettyPrinting()comparado con el valor compacto por defecto.