Serialización Jackson: ignorar valores vacíos (o null)


Actualmente estoy usando jackson 2.1.4 y estoy teniendo algunos problemas ignorando campos cuando estoy convirtiendo un objeto a una cadena JSON.

Aquí está mi clase que actúa como el objeto a convertir:

public class JsonOperation {

public static class Request {
    @JsonInclude(Include.NON_EMPTY)
    String requestType;
    Data data = new Data();

    public static class Data {
    @JsonInclude(Include.NON_EMPTY)
        String username;
        String email;
        String password;
        String birthday;
        String coinsPackage;
        String coins;
        String transactionId;
        boolean isLoggedIn;
    }
}

public static class Response {
    @JsonInclude(Include.NON_EMPTY)
    String requestType = null;
    Data data = new Data();

    public static class Data {
        @JsonInclude(Include.NON_EMPTY)
        enum ErrorCode { ERROR_INVALID_LOGIN, ERROR_USERNAME_ALREADY_TAKEN, ERROR_EMAIL_ALREADY_TAKEN };
        enum Status { ok, error };

        Status status;
        ErrorCode errorCode;
        String expiry;
        int coins;
        String email;
        String birthday;
        String pictureUrl;
        ArrayList <Performer> performer;
    }
}
}

Y así es como lo convierto:

ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);

JsonOperation subscribe = new JsonOperation();

subscribe.request.requestType = "login";

subscribe.request.data.username = "Vincent";
subscribe.request.data.password = "test";


Writer strWriter = new StringWriter();
try {
    mapper.writeValue(strWriter, subscribe.request);
} catch (JsonGenerationException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (JsonMappingException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

Log.d("JSON", strWriter.toString())

Aquí está la salida:

{"data":{"birthday":null,"coins":null,"coinsPackage":null,"email":null,"username":"Vincent","password":"test","transactionId":null,"isLoggedIn":false},"requestType":"login"}

¿Cómo puedo evitar esos valores nulos? ¡Solo quiero tomar la información requerida para el propósito de "suscripción"!

Aquí está exactamente la salida que estoy buscando:

{"data":{"username":"Vincent","password":"test"},"requestType":"login"}

Yo también probado @JsonInclude (Include.NON_NULL)y poner todas mis variables a null, pero tampoco funcionó! Gracias por su ayuda chicos!

Author: Paco Abato, 2013-04-18

8 answers

Tiene la anotación en el lugar equivocado - necesita estar en la clase, no en el campo. i. e:

@JsonInclude(Include.NON_NULL) //or Include.NON_EMPTY, if that fits your use case 
public static class Request {
  // ...
}

Como se señaló en los comentarios, en la versión 2.x+ la sintaxis para esta anotación es:

@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) // or JsonSerialize.Inclusion.NON_EMPTY

La otra opción es configurar el ObjectMapper directamente, simplemente llamando mapper.setSerializationInclusion(Include.NON_NULL);

(para que conste, creo que la popularidad de esta respuesta es una indicación de que esta anotación debería ser aplicable campo por campo * ejem @ fasterxml*)

 193
Author: drewmoore,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-14 13:24:07

También puede establecer la opción global:

objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
 40
Author: nomad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-08-01 00:26:54

También puedes intentar usar

@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)

Si usted está tratando con Jackson con la versión por debajo de 2+ (1.9.5) lo probé, se puede utilizar fácilmente esta anotación por encima de la clase. No para especificado para los atributos, solo para decleración de clase.

 14
Author: erhanasikoglu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-19 10:00:48

Necesita agregar com de importación.fasterxml.jackson.anotación.JsonInclude;

Añadir

@JsonInclude(JsonInclude.Include.NON_NULL)

Encima de POJO

Si has anidado POJO entonces

@JsonInclude(JsonInclude.Include.NON_NULL)

Necesita agregar todos los valores.

NOTA: JAXRS (Jersey ) maneja automáticamente este escenario 2.6 y superior.

 9
Author: vaquar khan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-03 14:19:37

Para Jackson 2.x

@JsonInclude(JsonInclude.Incluir.NON_NULL) justo antes del campo.

 4
Author: Gere,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-12 21:58:29

Estaba teniendo un problema similar recientemente con la versión 2.6.6.

@JsonInclude(JsonInclude.Include.NON_NULL)

El uso de la anotación anterior, ya sea a nivel archivado o de clase, no funcionaba como se esperaba. El POJO era mutable donde estaba aplicando la anotación. Cuando cambié el comportamiento del POJO para que fuera inmutable la anotación hizo su magia.

No estoy seguro de si su hasta la nueva versión o versiones anteriores de esta lib tenían un comportamiento similar, pero para 2.6.6 sin duda necesita tener POJO Inmutable para la anotación trabajar.

objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

La opción mencionada anteriormente en varias respuestas de establecer la inclusión de serialización en ObjectMapper directamente a nivel global también funciona, pero prefiero controlarla a nivel de clase o archivado.

Así que si desea que se ignoren todos los campos null mientras se serializa JSON, use la anotación a nivel de clase, pero si desea que solo se ignoren unos pocos campos en una clase, úselo sobre esos campos específicos. De esta manera es más legible y fácil de mantener si lo desea cambiar el comportamiento para una respuesta específica.

 2
Author: Amrut,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-19 11:18:56

O puedes usar GSON [https://code.google.com/p/google-gson / ], donde estos campos nulos se eliminarán automáticamente.

SampleDTO.java

public class SampleDTO {

    String username;
    String email;
    String password;
    String birthday;
    String coinsPackage;
    String coins;
    String transactionId;
    boolean isLoggedIn;

    // getters/setters
}

Prueba.java

import com.google.gson.Gson;

public class Test {

    public static void main(String[] args) {
        SampleDTO objSampleDTO = new SampleDTO();
        Gson objGson = new Gson();
        System.out.println(objGson.toJson(objSampleDTO));
    }
}

SALIDA:

{"isLoggedIn":false}

Usé gson-2.2.4

 2
Author: anij,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-13 06:27:41

El siguiente código puede ayudar si desea excluir el tipo booleano de la serialización:

@JsonInclude(JsonInclude.Include.NON_ABSENT)
 -1
Author: Alexander,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-12 17:06:44