2013-04-18 16 views
95

Attualmente sto usando jackson 2.1.4 e sto avendo qualche problema a ignorare i campi quando sto convertendo un oggetto in una stringa JSON.serializzazione Jackson: ignora valori vuoti (o null)

Ecco la mia classe che agisce come l'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 mi 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 può Evito quei valori nulli? Voglio solo prendere le informazioni richieste per lo scopo "abbonamento"!

Qui è esattamente l'output che sto cercando:

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

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

risposta

178

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, in versione 2.x + la sintassi per questa annotazione è:

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

L'altra opzione è quella di configurare il ObjectMapper direttamente, 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 su base campo per campo * ahem @faste RXML *)

+0

Non c'è davvero alcun modo per rendere attiva 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 desidero serializzare/deserializzare e sto solo inizializzando le variabili che devo usare a seconda della situazione. È un buon modo per farlo o dovrei fare classi severali contenenti solo le variabili di cui ho bisogno (in questo modo non avrei bisogno di usare alcuna annotazione, dato che non ci sarà mai una variabile nullo/vuoto) – Shinnyx

+0

Ahhh scusa, I guarda cosa sta succedendo ora. Vedi la mia risposta modificata. – drewmoore

+0

Funziona! Non posso credere che sia stato il problema ... Grazie drewmore! – Shinnyx

40

È anche possibile impostare l'opzione globale:

objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); 
13

Inoltre si può provare ad usare

@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) 

se avete a che fare con Jackson con la versione sotto 2+ (1.9.5) l'ho provato, puoi facilmente usare questa annotazione sopra la classe. Non specificato per gli attributi, solo per la declassazione di classe.

+1

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) – erhan

+0

la domanda richiede una versione particolare 2.1.4 – fd8s0

3

Oppure è possibile utilizzare GSON [https://code.google.com/p/google-gson/], dove questi campi nulli 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)); 
    } 
} 

USCITA:

{"isLoggedIn":false} 

ho usato GSON-2.2.4

+0

Attualmente il progetto utilizza ora GSON. Niente di sbagliato in Jackson, ma pochi bug relativi ad Android sono stati risolti usando GSON nelle mie esperienze personali. Grazie per la tua esclusione! Upvoted. – Shinnyx

5

Jackson 2.x

@JsonInclude (JsonInclude.Include.NON_NULL) poco prima del campo.

9

È necessario aggiungere import com.fasterxml.jackson.annotation.JsonInclude;

Aggiungere

@JsonInclude(JsonInclude.Include.NON_NULL) 

in cima POJO

Se si è annidato POJO poi

@JsonInclude(JsonInclude.Include.NON_NULL) 

necessità di aggiungere su ogni valori.

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

+0

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

+0

Sì, è possibile aggiungere sopra getter metodo esempio private int id; @JsonIgnore public int getId() { ID restituito; } –

2

Avevo problemi simili di recente con la versione 2.6.6.

@JsonInclude(JsonInclude.Include.NON_NULL) 

L'utilizzo dell'annotazione precedente a livello di file o di classe non funzionava come previsto. Il POJO era mutabile dove stavo applicando l'annotazione. Quando ho cambiato il comportamento del POJO per essere immutabile, l'annotazione ha funzionato nella sua magia.

Non sono sicuro che la sua versione precedente o precedente di questa versione abbia avuto un comportamento simile, ma per 2.6.6 è necessario avere POJO Immutable affinché l'annotazione funzioni.

objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); 

Sopra opzione menzionata in varie risposte di impostazione serializzazione inclusione nella ObjectMapper direttamente a livello globale funziona pure ma, preferisco controllandolo in classe o livello archiviato.

Quindi, se si desidera che tutti i campi nulli vengano ignorati mentre la serializzazione JSON utilizza l'annotazione a livello di classe ma se si desidera che solo pochi campi vengano ignorati in una classe, quindi utilizzarli su tali campi specifici. In questo modo è più facile leggere la manutenzione & se si desidera modificare il comportamento per una risposta specifica.

0

può essere raggiunto 2 modi:

  1. Mark POJO ignorare nulli/proprietà vuote

    import com.fasterxml.jackson.annotation.JsonInclude 
    
    @JsonInclude(Include.NON_NULL) // or @JsonInclude(Include.NON_EMPTY) 
    
  2. Configurare ObjectMapper che serializza il POJO/json come qui sotto:

    import com.fasterxml.jackson.annotation.JsonInclude; 
    import com.fasterxml.jackson.databind.ObjectMapper; 
    
    ObjectMapper mapper = new ObjectMapper();    
    mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); 
    
0

C l'ode può essere di aiuto se si desidera escludere il tipo booleano dalla serializzazione:

@JsonInclude(JsonInclude.Include.NON_ABSENT) 
Problemi correlati