Jackson-Serialisierung: leere Werte ignorieren (oder null)

138

Ich verwende derzeit Jackson 2.1.4 und habe Probleme, Felder zu ignorieren, wenn ich ein Objekt in eine JSON-Zeichenfolge konvertiere.

Hier ist meine Klasse, die als zu konvertierendes Objekt fungiert:

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 so konvertiere ich es:

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 die Ausgabe:

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

Wie kann ich diese Nullwerte vermeiden? Ich möchte die erforderlichen Informationen nur für den "Abonnement" -Zweck verwenden!

Hier ist genau die Ausgabe, die ich suche:

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

Ich habe auch @JsonInclude (Include.NON_NULL) ausprobiert und alle meine Variablen auf null gesetzt, aber es hat auch nicht funktioniert! Vielen Dank für Ihre Hilfe Jungs!

Shinnyx
quelle

Antworten:

246

Sie haben die Anmerkung an der falschen Stelle - sie muss sich in der Klasse befinden, 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, lautet die Syntax für diese Anmerkung in Versionen unter 2.x:

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

Die andere Möglichkeit besteht darin, das ObjectMapperdirekt zu konfigurieren , indem Sie einfach aufrufen mapper.setSerializationInclusion(Include.NON_NULL);

(Ich denke, die Popularität dieser Antwort ist ein Hinweis darauf, dass diese Anmerkung feldweise anwendbar sein sollte , @fasterxml)

zog mehr
quelle
Es gibt wirklich keine Möglichkeit, die include.NON_NULL-Annotation zum Laufen zu bringen? Oder die NON_EMTPY? Weil ich weiß, welches null sein wird, aber es hängt von der Situation ab. Ich verwende für jedes Objekt, das ich serialisieren / deserialisieren möchte, dieselbe "JsonOperation" -Klasse und initialisiere nur die Variablen, die ich je nach Situation verwenden muss. Ist dies ein guter Weg, oder sollte ich mehrere Klassen machen, die nur die Variablen enthalten, die ich benötige (auf diese Weise müsste ich keine Annotation verwenden, da es niemals eine null / leere Variable geben wird)
Shinnyx
26
Die Syntax wurde in der neuesten Version in @JsonSerialize (include = JsonSerialize.Inclusion.NON_NULL) und @JsonSerialize (include = JsonSerialize.Inclusion.NON_EMPTY) geändert. Wenn Sie sowohl nicht null als auch nicht leer benötigen, verwenden Sie @JsonSerialize (include = JsonSerialize) .Inclusion.NON_DEFAULT)
Maciej
1
Verwenden Sie @JsonSerialize (include = Inclusion.NON_NULL) vor dem Unterricht oder vor der Eigenschaft, die es funktionierte ...
Schwan
1
@drewmoore bitte nochmal überprüfen, @JsonInclude(JsonSerialize.Inclusion.NON_NULL) sollte sein @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)und es ist auch der alte veraltete Weg. Sie sollten also "in Version unter 2.x"
schreiben
2
2. + verwenden@JsonInclude(Include.NON_NULL)
Honghe.Wu
48

Sie können auch die globale Option festlegen:

objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
Nomade
quelle
15

Sie können auch versuchen, zu verwenden

@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)

Wenn Sie es mit Jackson mit einer Version unter 2+ (1.9.5) zu tun haben, die ich getestet habe, können Sie diese Anmerkung leicht über der Klasse verwenden. Nicht für die Attribute angegeben, nur für die Klassendekleration.

Erhanasikoglu
quelle
2
include-Attribut von JsonSerialize ist zugunsten von JsonInclude
fd8s0
2
wie ich schon sagte: mit jackson mit version unter 2+ (1.9.5)
erhanasikoglu
Die Frage fragt nach einer bestimmten Version 2.1.4
fd8s0
14

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

Hinzufügen

@JsonInclude(JsonInclude.Include.NON_NULL)

auf POJO

Wenn Sie POJO dann verschachtelt haben

@JsonInclude(JsonInclude.Include.NON_NULL)

müssen alle Werte hinzufügen.

HINWEIS: JAXRS (Jersey) behandelt dieses Szenario ab Version 2.6 automatisch.

Vaquar Khan
quelle
Gibt es eine ähnliche Funktionalität bei Verwendung des alten Pakets org.codehaus.jackson.annotate?
pkran
Ja, Sie können zusätzlich zum Beispiel der Getter-Methode eine private int-ID hinzufügen. @JsonIgnore public int getId () {return id; }
Vaquar Khan
1
Gleich wie bestehende Antworten
Karl Richter
4

Für Jackson 2.x.

@JsonInclude(JsonInclude.Include.NON_NULL)

kurz vor dem Feld.

Gere
quelle
2
Gleich wie bestehende Antworten
Karl Richter
2

Ich hatte kürzlich ein ähnliches Problem mit Version 2.6.6.

@JsonInclude(JsonInclude.Include.NON_NULL)

Die Verwendung der obigen Anmerkung auf Datei- oder Klassenebene funktionierte nicht wie erwartet. Das POJO war veränderlich, wo ich die Anmerkung anwendete. Als ich das Verhalten des POJO so änderte, dass es unveränderlich war, wirkte die Anmerkung magisch.

Ich bin nicht sicher, ob es sich um eine neue Version oder frühere Versionen dieser Bibliothek handelt, aber für 2.6.6 benötigen Sie sicherlich unveränderliches POJO, damit die Anmerkung funktioniert.

objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

Die oben in verschiedenen Antworten erwähnte Option zum Festlegen der Serialisierungseinbeziehung in ObjectMapper direkt auf globaler Ebene funktioniert ebenfalls, ich bevorzuge jedoch die Steuerung auf Klassen- oder Ablageebene.

Wenn Sie also möchten, dass alle Nullfelder während der JSON-Serialisierung ignoriert werden, verwenden Sie die Annotation auf Klassenebene. Wenn Sie jedoch möchten, dass nur wenige Felder in einer Klasse ignoriert werden, verwenden Sie sie über diesen bestimmten Feldern. Auf diese Weise ist es besser lesbar und einfach zu warten, wenn Sie das Verhalten für eine bestimmte Reaktion ändern möchten.

Amrut
quelle
2

Sie können auch GSON [ https://code.google.com/p/google-gson/ ] verwenden, bei dem 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));
    }
}

AUSGABE:

{"isLoggedIn":false}

Ich habe gson-2.2.4 verwendet

anij
quelle
-1

Der folgende Code kann hilfreich sein, wenn Sie den booleschen Typ von der Serialisierung ausschließen möchten:

@JsonInclude(JsonInclude.Include.NON_ABSENT)
Alexander
quelle
1
Gleich wie bestehende Antworten
Karl Richter