2013-04-18 11 views
95

Ich benutze derzeit Jackson 2.1.4 und ich habe Probleme beim Ignorieren von Feldern, wenn ich ein Objekt in eine JSON-Zeichenfolge konvertieren.Jackson Serialisierung: leere Werte (oder null) ignorieren

Hier ist meine Klasse, die wirkt als das Objekt umgewandelt werden:

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

Und hier ist, wie ich es konvertieren:

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

Hier ist der Ausgang:

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

Wie kann Ich vermeide diese Nullwerte? Ich möchte nur die erforderlichen Informationen für den "Abonnement" Zweck nehmen!

Hier ist genau die Ausgabe, die ich suche:

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

Ich habe auch versucht @JsonInclude (Include.NON_NULL) und meine Variablen alle auf null gesetzt, aber es hat nicht funktioniert! Danke für eure Hilfe!

Antwort

178

Sie haben die Annotation an der falschen Stelle - sie muss auf der Klasse sein, nicht auf dem Feld. dh:

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

Wie in den Kommentaren erwähnt, in der Version 2.x + die Syntax für diese Anmerkung ist:

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

Die andere Option ist die ObjectMapper direkt zu konfigurieren, einfach durch mapper.setSerializationInclusion(Include.NON_NULL);

Aufruf

(für die Aufzeichnung, ich denke, die Popularität dieser Antwort ist ein Hinweis darauf, dass diese Anmerkung Feld für Feld anwendbar sein sollte * ahem @faste rxml *)

+0

Es gibt wirklich keine Möglichkeit, die Include.NON_NULL Annotation zu arbeiten? Oder die NON_EMTPY? Weil ich weiß, welcher Null sein wird, aber es hängt von der Situation ab.Ich verwende dieselbe "JsonOperation" -Klasse für jedes Objekt, das ich serialisieren/deserialisieren möchte, und ich initialisiere nur die Variablen, die ich abhängig von der Situation verwenden muss. Ist dies ein guter Weg, um es zu tun, oder ich sollte mehrere Klassen nur mit den Variablen, die ich brauche, tun (so würde ich keine Annotation verwenden, da es nie eine Null/leere Variable geben wird) – Shinnyx

+0

Ahhh Entschuldigung, ich Sieh dir an, was gerade passiert. Siehe meine bearbeitete Antwort. – drewmoore

+0

Es funktioniert! Ich kann nicht glauben, dass das das Problem war ... Danke nochmal! – Shinnyx

40

Sie können auch die globale Option:

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

Sie können auch versuchen

@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) 

zu verwenden, wenn Sie mit jackson mit Version handelt unter 2+ (1.9.5) Ich habe es getestet, Sie können diese Annotation einfach oberhalb der Klasse verwenden. Nicht für die Attribute angegeben, nur für die Klassen-Deklaration.

+1

include-Attribut von JsonSerialize ist veraltet zugunsten von JsonInclude – fd8s0

+2

wie gesagt: mit jackson mit Version unter 2+ (1.9.5) – erhan

+0

Die Frage fragt nach einer bestimmten Version 2.1.4 – fd8s0

3

Oder Sie können GSON [], wo diese Nullfelder automatisch entfernt werden.

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

OUTPUT:

{"isLoggedIn":false} 

I verwendet Gson-2.2.4

+0

Tatsächlich verwendet das Projekt jetzt GSON. Nichts ist falsch mit Jackson, aber einige Android-Bug wurden gelöst, indem Sie GSON in meinen persönlichen Erfahrungen verwenden. Danke für deinen Beitrag! Upvoted. – Shinnyx

5

Für jackson 2.x

@JsonInclude (JsonInclude.Include.NON_NULL) kurz vor dem Feld.

9

Sie müssen import com.fasterxml.jackson.annotation.JsonInclude hinzufügen;

hinzufügen

@JsonInclude(JsonInclude.Include.NON_NULL) 

oben auf POJO

Wenn Sie POJO dann auf alle Werte

@JsonInclude(JsonInclude.Include.NON_NULL) 

Bedarf hinzufügen verschachtelt haben.

HINWEIS: JAXRS (Jersey) behandelt automatisch dieses Szenario 2.6 und höher.

+0

gibt es eine ähnliche Funktionalität bei der Verwendung des alten org.codehaus.jackson.annotate Pakets? – pkran

+0

Ja, Sie können oben auf Getter-Methode Beispiel private Int ID hinzufügen; @ JsonIgnore public int getId() { Rückgabe-ID; } –

2

Ich hatte vor kurzem ein ähnliches Problem mit der Version 2.6.6.

@JsonInclude(JsonInclude.Include.NON_NULL) 

Die obige Annotation entweder auf der archivierten oder Klassenebene funktioniert nicht wie erwartet. Das POJO war veränderlich, wo ich die Anmerkung anwendete. Als ich das Verhalten des POJO als unveränderlich änderte, wirkte die Annotation wie magisch.

Ich bin mir nicht sicher, ob seine neue Version oder frühere Versionen dieser Bibliothek ein ähnliches Verhalten hatten, aber für 2.6.6 müssen Sie unbedingt Unveränderlich POJO für die Annotation arbeiten.

objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); 

Above Option in verschiedenen Antworten erwähnt Serialisierung Aufnahme in ObjectMapper direkt auf globaler Ebene der Einstellung funktioniert auch, aber ich es auf Klasse oder eingereicht Ebene bevorzugen steuern.

Wenn Sie also möchten, dass alle Nullfelder während der JSON-Serialisierung ignoriert werden, verwenden Sie die Annotation auf Klassenebene. Wenn Sie jedoch nur wenige Felder in einer Klasse ignorieren möchten, verwenden Sie sie über diesen spezifischen Feldern. Auf diese Weise ist es besser lesbar & einfach für die Wartung, wenn Sie Verhalten für spezifische Antwort ändern wollten.

0

es 2 Möglichkeiten erreicht werden kann:

  1. Markieren Sie die POJO null/leer Eigenschaften zu ignorieren

    import com.fasterxml.jackson.annotation.JsonInclude 
    
    @JsonInclude(Include.NON_NULL) // or @JsonInclude(Include.NON_EMPTY) 
    
  2. konfigurieren ObjectMapper, die als unter den POJO/json serialisiert:

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

C ode balgen kann helfen, wenn Sie booleschen Typ von Serialisierung entweder ausschließen möchten:

@JsonInclude(JsonInclude.Include.NON_ABSENT) 
Verwandte Themen