Artículo

Cómo Ignorar Campos Dinámicamente en Java con Jackson

Introducción En este tutorial, aprenderemos cómo ignorar campos dinámicamente en Jackson. Este conocimiento es crucial para programadores que desean serializar y deserializar objetos en Java de manera flexible, dependiendo de condiciones específicas. Examinaremos tres enfoques para lograr este objetivo: @JsonFilter, @JsonView y Jackson Mixins. Configuración del Proyecto Para comenzar con este tutorial, debemos añadir la […]

Cómo Ignorar Campos Dinámicamente en Java con Jackson

Introducción

En este tutorial, aprenderemos cómo ignorar campos dinámicamente en Jackson. Este conocimiento es crucial para programadores que desean serializar y deserializar objetos en Java de manera flexible, dependiendo de condiciones específicas. Examinaremos tres enfoques para lograr este objetivo: @JsonFilter, @JsonView y Jackson Mixins.

Configuración del Proyecto

Para comenzar con este tutorial, debemos añadir la biblioteca necesaria de Jackson a nuestro proyecto. Aquí tienes el fragmento de código que debes incluir en tu archivo pom.xml si utilizas Maven:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.17.2</version>
</dependency>

La última versión puede ser consultada aquí.

Ignorar Dinámicamente Usando @JsonFilter

El primer enfoque que examinaremos es mediante una anotación que especifica un filtro que se utilizará durante la serialización. Al anotar una clase con @JsonFilter, podemos configurar dinámicamente qué campos se incluirán durante la serialización.

Ejemplo de Código

import com.fasterxml.jackson.annotation.JsonFilter;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;

@JsonFilter("publicFilter")
public class UserWithFilter {
    private Long id;
    private String name;

    // Constructor, getters y setters
    public UserWithFilter(Long id, String name) {
        this.id = id;
        this.name = name;
    }
    public Long getId() {
        return id;
    }
    public String getName() {
        return name;
    }
}
// En tu método principal
SimpleFilterProvider filterProvider = new SimpleFilterProvider();
filterProvider.addFilter("publicFilter", SimpleBeanPropertyFilter.serializeAllExcept("id"));
ObjectMapper objectMapper = new ObjectMapper().setFilterProvider(filterProvider);

UserWithFilter user = new UserWithFilter(1000L, "John");
String result = objectMapper.writeValueAsString(user);
System.out.println(result); // Debería contener "John" y no el "1000"

Este método proporciona una gran flexibilidad, ya que nos permite escoger qué campos serializar en tiempo de ejecución. Sin embargo, no funciona para la deserialización; incluso si personalizamos el ObjectMapper con el mismo filtro, el campo id será unmarshalled en el objeto.

Deserialización

String json = "{\"id\":1000,\"name\":\"John\"}";
UserWithFilter result = objectMapper.readValue(json, UserWithFilter.class);
System.out.println(result.getId());    // Imprime "1000"
System.out.println(result.getName());   // Imprime "John"

Ignorar Condicionalmente Usando @JsonView

A diferencia del enfoque anterior, @JsonView permite controlar la visibilidad de los campos al definir diferentes vistas. Esta opción debe definirse en tiempo de compilación.

Ejemplo de Código

import com.fasterxml.jackson.annotation.JsonView;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;

public class UserWithView {
    @JsonView(InternalView.class)
    private Long id;
    @JsonView(PublicView.class)
    private String name;

    // Constructor, getters y setters
    public UserWithView(Long id, String name) {
        this.id = id;
        this.name = name;
    }
    public Long getId() {
        return id;
    }
    public String getName() {
        return name;
    }

    public interface PublicView {}
    public interface InternalView extends PublicView {}
}
// En tu método principal
ObjectWriter objectWriter = new ObjectMapper().writerWithView(UserWithView.PublicView.class);
String result = objectWriter.writeValueAsString(user);
System.out.println(result); // Debería contener "John" y no el "1000"

Este enfoque también funciona bien durante la deserialización:

Deserialización

String json = "{\"id\":1000,\"name\":\"John\"}";
ObjectReader objectReader = new ObjectMapper().readerWithView(UserWithView.PublicView.class)
    .forType(UserWithView.class);
UserWithView user = objectReader.readValue(json);
System.out.println(user.getName()); // Imprime "John"

Usar Mixins para Aplicar @JsonIgnore Dinámicamente

Los Mixins de Jackson nos permiten aplicar anotaciones como @JsonIgnore sin modificar la clase original. Necesitamos definir una interfaz con un método getter en la propiedad que queremos ignorar.

Ejemplo de Código

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.ObjectMapper;

public interface PublicMixin {
    @JsonIgnore
    Long getId();
}
// En tu método principal
ObjectMapper objectMapper = new ObjectMapper().addMixIn(UserWithMixin.class, PublicMixin.class);
String result = objectMapper.writeValueAsString(user);
System.out.println(result); // Debería contener "John" y no el "1000"
// Deserialización
String json = "{\"id\":1000,\"name\":\"John\"}";
UserWithMixin user = objectMapper.readValue(json, UserWithMixin.class);
System.out.println(user.getId()); // Debería ser null
System.out.println(user.getName()); // Imprime "John"

Comparando los Enfoques

EnfoqueFlexibilidad RuntimeCaso de UsoSerialización / Deserialización
@JsonFilterAltaExcluir campos dinámicamente en tiempo de ejecuciónNo
@JsonViewMediaDefinir múltiples vistas de serialización
MixinsMediaAplicar @JsonIgnore sin modificar la clase original

La elección del enfoque depende de la necesidad de flexibilidad en tiempo de ejecución y si es crucial que la deserialización funcione correctamente.

Conclusión

En este artículo, hemos explorado varios enfoques para lograr la dinámica en la serialización y deserialización de objetos con Jackson. Aunque la plena dinámica en lenguajes compilados como Java puede ser difícil de alcanzar, Jackson proporciona varios mecanismos para personalizar el comportamiento de la serialización y adaptar las salidas según diferentes necesidades en tiempo de ejecución.

Implementar estos enfoques te ayudará a manejar con eficacia cómo se representan los datos en tu aplicación, mejorando la versatilidad de tu código Java.

¿Quieres acelerar tu carrera como desarrollador Java?

Reserva una Sesión de Estrategia Técnica gratuita y descubre cómo pasar de Junior a Senior en menos tiempo del que imaginas.

  • Diagnóstico personalizado de tu nivel técnico
  • Plan de acción para conseguir tu próximo ascenso
  • Mentoría 1-a-1 enfocada en resultados

⚡ Plazas disponibles limitadas

Compartir artículo