Jackson Annotation Examples

Jackson Annotation Examples

❗Para estos ejemplos se necesita la dependencia de jackson databind

En este tutorial, vamos a profundizar en las anotaciones de Jackson. Veremos cómo utilizar las anotaciones existentes, cómo crear anotaciones personalizadas y, por último, cómo desactivarlas.

2. Jackson Serialization Annotations

@JsonAnyGetter

La anotacion @JsonAnyGeter permite serializar propiedades adicionales o dinámicas de un objeto como parte del JSON generado. Es útil cuando no se conoce de antemano qué propiedades estarán presentes en un objeto o cuando se quiere serializar un conjunto de valores que están almacenados en un mapa (Map<String, Object>)

public class ExtendableBean {
    public String name;
    private Map<String, String> properties;

    @JsonAnyGetter
    public Map<String, String> getProperties() {
        return properties;
    }
}

Cuando serializamos una instancia de este clase, obtenemos todos los valores clave del Mapa como propiedades estándar:

{
    "name":"My bean",
    "attr2":"val2",
    "attr1":"val1"
}

Así es como se ve en la práctica la serialización de esta entidad:

@Test
public void whenSerializingUsingJsonAnyGetter_thenCorrect()
  throws JsonProcessingException {
 
    ExtendableBean bean = new ExtendableBean("My bean");
    bean.add("attr1", "val1");
    bean.add("attr2", "val2");

    String result = new ObjectMapper().writeValueAsString(bean);
 
    assertThat(result, containsString("attr1"));
    assertThat(result, containsString("val1"));
}

@JsonGetter

La anotación @JsonGetter es una alternativa a la anotación @JsonProperty, que marca un método como método getter. En el siguiente ejemplo, especificamos el método getTheName() como método getter de la propiedad name de una entidad MyBean:

public class MyBean {
    public int id;
    private String name;

    @JsonGetter("name")
    public String getTheName() {
        return name;
    }
}

Así es como funciona en la practica:

@Test
public void whenSerializingUsingJsonGetter_thenCorrect()
  throws JsonProcessingException {
 
    MyBean bean = new MyBean(1, "My bean");

    String result = new ObjectMapper().writeValueAsString(bean);
 
    assertThat(result, containsString("My bean"));
    assertThat(result, containsString("1"));
}

@JsonPropertyOrder

Permite definir el orden de los elementos que se van a serializar

@JsonPropertyOrder({ "name", "id" })
public class MyBean {
    public int id;
    public String name;
}

El output sería el siguiente:

{
    "name":"My bean",
    "id":1
}

@JsonRawValue

Permite serializar en crudo propiedades que ya son json

@AllArgsConstructor
public class RawBean {

    public String name;

    @JsonRawValue
    public String json;

}

Ejemplo en código

RawBean bean = new RawBean("My bean",  "{\"attr\":false}");

String result = new ObjectMapper().writeValueAsString(bean);
System.out.println(result);

Así seria el ouput con la anotación y sin la anotación:

Sin la anotación: {"name":"My bean","json":{\"attr\":false}}
Con la anotación: {"name":"My bean","json":{"attr":false}}

@JsonValue

Esta anotación indica un único método que se usará para serializar la instancia entera. Por ejemplo en un enum, podemos indicar que se serialice por su método getName

@AllArgsConstructor
public enum TypeEnumWithValue {
    TYPE1(1, "Type A"), TYPE2(2, "Type 2");

    private Integer id;
    private String name;

    // standard constructors

    @JsonValue
    public String getName() {
        return name;
    }
}

Ejemplo:

    public void testWhenSerializingUsingJsonValue()
            throws JsonParseException, IOException {

        String enumAsString = new ObjectMapper()
                .writeValueAsString(TypeEnumWithValue.TYPE1);

        assertEquals(enumAsString, "\"Type A\"");
    }

https://www.baeldung.com/jackson-annotations#6-jsonrootname