Cómo leer y procesar un archivo JSON en Spring Boot usando JsonNode

En esta entrada, te mostraré cómo leer un archivo JSON en Spring Boot y procesarlo utilizando la clase JsonNode de la biblioteca Jackson. Esto te permitirá extraer información de archivos JSON de forma eficiente y trabajar con los datos en tu aplicación.

Paso 1: Configuración del Proyecto

Para este tutorial, utilizaremos un proyecto de Spring Boot. Si aún no tienes un proyecto listo, puedes crearlo fácilmente utilizando Spring Initializr, asegurándote de incluir la dependencia de Spring Web.

Paso 2: Creando el Archivo JSON

El siguiente es el archivo JSON que leeremos desde el classpath de nuestro proyecto. Este archivo se llamará product.json y contiene información sobre un producto:

JSON
{
  "productId": 12345,
  "name": "Wireless Headphones",
  "price": 99.99,
  "inStock": true,
  "tags": [
    "electronics",
    "audio"
  ],
  "releaseDate": null,
  "dimensions": {
    "width": 15.2,
    "height": 18.0,
    "depth": 7.5,
    "unit": "cm"
  },
  "ratings": [5, 4, 3, 5, 4]
}

El archivo describe un producto con varios campos, incluidos un arreglo de etiquetas (tags) y un arreglo de calificaciones de usuarios (ratings).

Paso 3: Controlador para Leer el Archivo JSON

A continuación, crearemos un controlador en Spring Boot que leerá este archivo JSON desde el classpath y procesará cada campo, incluyendo los arreglos de etiquetas y calificaciones. Utilizaremos Jackson y su clase JsonNode para manejar los datos.

Java
package com.example.json;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.core.io.ClassPathResource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

@RestController
@RequestMapping("/api/products")
public class ProductController {

    @GetMapping("/json-node")
    public void getProductFromJsonNode() throws IOException {
        // Ruta del archivo JSON en el classpath
        ClassPathResource resource = new ClassPathResource("product.json");
        // Leer el archivo JSON como String
        String contenidoArchivo = new String(Files.readAllBytes(Paths.get(resource.getURI())));
        ObjectMapper objectMapper = new ObjectMapper();
        // Convertir el JSON a un objeto JsonNode
        JsonNode jsonNode = objectMapper.readTree(contenidoArchivo);

        // Recuperar las propiedades del JSON
        int productId = jsonNode.get("productId").asInt();
        String name = jsonNode.get("name").asText();
        double price = jsonNode.get("price").asDouble();
        boolean inStock = jsonNode.get("inStock").asBoolean();
        String releaseDate = jsonNode.get("releaseDate").asText(null); // Manejar null

        // Acceder a subcampos (dimensiones)
        JsonNode dimensionsNode = jsonNode.get("dimensions");
        double width = dimensionsNode.get("width").asDouble();
        double height = dimensionsNode.get("height").asDouble();
        double depth = dimensionsNode.get("depth").asDouble();
        String unit = dimensionsNode.get("unit").asText();

        // Leer el arreglo de tags como List<String> usando Stream
        JsonNode tagsNode = jsonNode.get("tags");
        List<String> tags = StreamSupport.stream(tagsNode.spliterator(), false).map(JsonNode::asText).collect(Collectors.toList());

        // Leer el arreglo de ratings como List<Integer> usando Stream
        JsonNode ratingsNode = jsonNode.get("ratings");
        List<Integer> ratings = StreamSupport.stream(ratingsNode.spliterator(), false).map(JsonNode::asInt).collect(Collectors.toList());

        // Mostrar las propiedades en consola
        System.out.println("Product ID: " + productId);
        System.out.println("Name: " + name);
        System.out.println("Price: " + price);
        System.out.println("In Stock: " + inStock);
        System.out.println("Release Date: " + (releaseDate != null ? releaseDate : "No date available"));

        System.out.println("Dimensions:");
        System.out.println("  Width: " + width + " " + unit);
        System.out.println("  Height: " + height + " " + unit);
        System.out.println("  Depth: " + depth + " " + unit);

        // Mostrar el arreglo de tags
        System.out.println("Tags:");
        tags.forEach(tag -> System.out.println("  - " + tag));

        // Mostrar el arreglo de ratings
        System.out.println("Ratings:");
        ratings.forEach(rating -> System.out.println("  - " + rating));
    }
    
}

Explicación del Código
  1. Lectura del Archivo JSON: Usamos ClassPathResource para cargar el archivo product.json desde el classpath de nuestro proyecto, y luego lo leemos como un String utilizando Files.readAllBytes().
  2. Conversión a JsonNode: Utilizamos la clase ObjectMapper de Jackson para convertir el contenido del archivo en un objeto de tipo JsonNode, que nos permite navegar por el JSON y acceder a sus propiedades de forma muy flexible.
  3. Extracción de Datos:
    • Propiedades Básicas: Accedemos directamente a los valores como productId, name, price, inStock, y releaseDate utilizando los métodos asInt(), asText(), asDouble(), y asBoolean().
    • Subcampos (dimensiones): Para acceder a campos dentro de un objeto anidado como dimensions, primero accedemos al nodo padre y luego extraemos los valores internos.
    • Arreglos (tags y ratings): Utilizamos StreamSupport.stream() para recorrer los nodos del JSON que contienen arreglos, y luego mapeamos los valores de cada nodo a un List de Java. Los tags se convierten a un List y los ratings a un List.
  4. Impresión de Resultados: Finalmente, mostramos los valores extraídos en la consola.
Paso 4: Resultado

Al ejecutar este código, verás algo como esto en la consola:

Java
Product ID: 12345
Name: Wireless Headphones
Price: 99.99
In Stock: true
Release Date: No date available
Dimensions:
  Width: 15.2 cm
  Height: 18.0 cm
  Depth: 7.5 cm
Tags:
  - electronics
  - audio
Ratings:
  - 5
  - 4
  - 3
  - 5
  - 4

Conclusión

En esta entrada, hemos visto cómo leer y procesar un archivo JSON en Spring Boot utilizando Jackson y la clase JsonNode. Este enfoque es muy útil cuando trabajas con archivos JSON cuyos esquemas pueden cambiar o cuando no quieres crear clases POJO dedicadas. Además, hemos mostrado cómo manejar arreglos dentro del JSON y convertirlos a listas en Java usando Stream.

Espero que este tutorial te haya sido útil. Si tienes alguna duda o sugerencia, ¡no dudes en dejar un comentario!