Ignorar campos con JsonIgnore
Cuando dejamos que Jackson serialice una clase o un registro a JSON o XML para devolverlo en nuestra API Quarkus, nos encontraremos en ocasiones que hay información que preferiríamos no hacer visible. Por ejemplo, puede que querramos ocultar el identificador, o los campos de fecha de creación y modificación.
Con la anotación @JsonIgnore (importable desde com.fasterxml.jackson.annotation.JsonIgnore), podemos pedirle a Jackson que excluya esa propiedad cuando esté generando el JSON o el XML correspondiente. En el siguiente ejemplo, inicialmente la API nos devuelve todas las propiedades de un género:
{
"id": 2,
"name": "Poesía",
"createdAt": "2023-07-23T12:04:37",
"updatedAt": "2023-07-23T12:07:28"
}
Sin embargo, si le añadimos esta anotación a los campos createdAt y updatedAt:
@CreationTimestamp
@JsonIgnore
private LocalDateTime createdAt;
@UpdateTimestamp
@JsonIgnore
private LocalDateTime updatedAt;
La próxima vez que visitemos ese endpoint ya no se incluirán en la respuesta:
{
"id": 2,
"name": "Poesía"
}
Renombrar campos con JsonProperty
Por defecto, Jackson usará el nombre del campo de Java como fuente para la clave del campo JSON que se usa al pasar una clase a JSON o al convertir de JSON a instancia de clase. Con la anotación JsonProperty, importable desde com.fasterxml.jackson.annotation.JsonProperty, podemos cambiar el nombre dado. Por ejemplo, si anotamos un campo name del siguiente modo:
@JsonProperty("genreName")
private String name;
Ahora el JSON tendrá el siguiente aspecto:
{
"id": 2,
"genreName": "Poesía"
}
No solo eso, sino que también cambiará la forma de declarar el campo cuando queramos insertar o modificar elementos. Por lo tanto, lo siguiente ya no será válido:
# POST /genres
{
"name": "Psicología"
}
Ahora tendrá que ser indicado del siguiente modo:
# POST /genres
{
"genreName": "Psicología"
}
Permitir darle varios nombres a una key con JsonAlias
Si no queremos ese comportamiento colateral que nos provoca JsonProperty en los payloads de entrada, podemos usar la anotación JsonAlias. Esta anotación es importable desde com.fasterxml.jackson.annotation.JsonAlias y recibe como parámetro un array con todos los nombres de key que mapearán contra este campo cuando se deserialicen objetos JSON. Eso significa que cuando le pasemos a la API un payload JSON, será válido cualquiera de los nombres dados a la hora de elegir el campo del JSON que tiene que almacenarse en esa key.
Por lo tanto, si lo combinamos del siguiente modo:
@JsonProperty("genreName")
@JsonAlias({ "genreName", "name" })
private String name;
Ahora tanto genreName como name serán nombres válidos de clave que se pueden proporcionar en el JSON. El siguiente objeto es válido:
{
"genreName": "Criminología"
}
Pero el siguiente objeto también es válido, porque el alias establece que puede llamarse así:
{
"name": "Sociología"
}
A tener en cuenta que esto solo afecta a las entradas de datos. Para las salidas de datos tiene preferencia el nombre real del campo o el que se haya declarado mediante JsonProperty:
# POST /genres
{
"name": "Humanismo"
}
# "HTTP 200 OK"
{
"id": 46,
"genreName": "Humanismo"
}
Campos virtuales
Un último apunte: para Jackson, cualquier getter será considerado parte de algo a serializar salvo que se excluya con JsonIgnore. Podemos aprovechar esto para fabricar campos con keys virtuales que realmente no procedan de base de datos. En el siguiente ejemplo, le agregamos a la clase Genre un getter llamado getLongitud() que calcula el ancho del nombre:
public class Genre {
private String name;
public int getLongitud() {
return name.length;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Bueno, pues al haber hecho esto, implícitamente y salvo que lo cambiemos con la anotación JsonIgnore, ahora se incluirá el nuevo campo en las respuestas:
{
"id": 5,
"name": "Parapsicología",
"longitud": 14
}