Serializzazione Jackson: ignora valori vuoti (o null)


139

Attualmente sto usando Jacksonson 2.1.4 e ho dei problemi nell'ignorare i campi quando sto convertendo un oggetto in una stringa JSON.

Ecco la mia classe che funge da oggetto da convertire:

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;
    }
}
}

Ed ecco come lo converto:

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())

Ecco l'output:

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

Come posso evitare quei valori nulli? Voglio solo prendere le informazioni richieste a scopo di "abbonamento"!

Ecco esattamente l'output che sto cercando:

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

Ho anche provato @JsonInclude (Include.NON_NULL) e ho messo a zero tutte le mie variabili, ma non ha funzionato neanche! Grazie per il vostro aiuto ragazzi!


Risposte:


247

Hai l'annotazione nel posto sbagliato - deve essere sulla classe, non sul campo. vale a dire:

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

Come notato nei commenti, nelle versioni inferiori a 2.x la sintassi per questa annotazione è:

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

L'altra opzione è quella di configurare ObjectMapperdirettamente, semplicemente chiamando mapper.setSerializationInclusion(Include.NON_NULL);

(per la cronaca, penso che la popolarità di questa risposta sia un'indicazione che questa annotazione dovrebbe essere applicabile campo per campo, @fasterxml)


Non c'è davvero modo di far funzionare l'annotazione include.NON_NULL? O quello NON_EMTPY? Perché so quale sarà nullo, ma dipende dalla situazione. Sto usando la stessa classe "JsonOperation" per ogni oggetto che voglio serializzare / deserializzare e sto inizializzando solo le variabili che devo usare a seconda della situazione. È un buon modo per farlo o dovrei fare delle classi per i sever che contengono solo le variabili di cui ho bisogno (in quel modo non dovrei usare nessuna annotazione, dal momento che non ci sarà mai una variabile nulla / vuota)
Shinnyx

26
La sintassi è stata modificata nella versione più recente in @JsonSerialize (include = JsonSerialize.Inclusion.NON_NULL) e @JsonSerialize (include = JsonSerialize.Inclusion.NON_EMPTY Se hai bisogno sia di null che di non vuoto, usa @JsonSerialize (include = JsonSerialize .Inclusion.NON_DEFAULT)
Maciej,

1
Usa @JsonSerialize (include = Inclusion.NON_NULL) prima della lezione o prima che funzionasse ...
cigno

1
@drewmoore, ricontrolla, @JsonInclude(JsonSerialize.Inclusion.NON_NULL) dovrebbe essere @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)ed è anche il vecchio modo deprecato. quindi dovresti scrivere "nella versione sotto 2.x", non "nella versione 2.x +"
WestFarmer

2
2. + uso@JsonInclude(Include.NON_NULL)
Honghe.Wu

48

Puoi anche impostare l'opzione globale:

objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

15

Inoltre puoi provare a usare

@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)

se hai a che fare con Jackson con versione precedente alla 2+ (1.9.5) l'ho testato, puoi facilmente usare questa annotazione sopra la classe. Non per specificato per gli attributi, solo per la declerazione di classe.


2
include l'attributo di JsonSerialize è deprecato a favore di JsonInclude
fd8s0

2
come ho detto: con jackson con versione inferiore a 2+ (1.9.5)
erhanasikoglu

la domanda si pone su una particolare versione 2.1.4
fd8s0

14

Devi aggiungere import com.fasterxml.jackson.annotation.JsonInclude;

Inserisci

@JsonInclude(JsonInclude.Include.NON_NULL)

in cima a POJO

Se hai annidato POJO allora

@JsonInclude(JsonInclude.Include.NON_NULL)

è necessario aggiungere ogni valore.

NOTA: JAXRS (Jersey) gestisce automaticamente questo scenario 2.6 e versioni successive.


esiste una funzionalità simile quando si utilizza il vecchio pacchetto org.codehaus.jackson.annotate?
pkran,

Sì, puoi aggiungere l'esempio int int privato metodo getter; @JsonIgnore public int getId () {return id; }
vaquar khan,

1
Stesse risposte esistenti
Karl Richter,

4

Per jackson 2.x

@JsonInclude(JsonInclude.Include.NON_NULL)

appena prima del campo.


2
Stesse risposte esistenti
Karl Richter,

2

Di recente ho riscontrato un problema simile con la versione 2.6.6.

@JsonInclude(JsonInclude.Include.NON_NULL)

L'uso dell'annotazione sopra riportata a livello di file o di classe non funzionava come previsto. Il POJO era mutevole nel punto in cui stavo applicando l'annotazione. Quando ho cambiato il comportamento del POJO per renderlo immutabile, l'annotazione ha funzionato in modo magico.

Non sono sicuro che si tratti di una nuova versione o di versioni precedenti di questa libreria con un comportamento simile, ma per 2.6.6 sicuramente devi avere Immutable POJO affinché l'annotazione funzioni.

objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

L'opzione sopra menzionata in varie risposte sull'impostazione dell'inclusione della serializzazione in ObjectMapper funziona anche a livello globale, ma preferisco controllarlo a livello di classe o archiviato.

Pertanto, se si desidera ignorare tutti i campi Null durante la serializzazione JSON, utilizzare l'annotazione a livello di classe, ma se si desidera ignorare solo pochi campi in una classe, utilizzarli su quei campi specifici. In questo modo è più leggibile e facile per la manutenzione se si desidera modificare il comportamento per una risposta specifica.


2

Oppure puoi utilizzare GSON [ https://code.google.com/p/google-gson/ ], dove questi campi null verranno automaticamente rimossi.

SampleDTO.java

public class SampleDTO {

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

    // getters/setters
}

Test.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));
    }
}

PRODUZIONE:

{"isLoggedIn":false}

Ho usato gson-2.2.4


-1

Il codice seguente può essere utile se si desidera escludere il tipo booleano dalla serializzazione:

@JsonInclude(JsonInclude.Include.NON_ABSENT)

1
Stesse risposte esistenti
Karl Richter
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.