ジャクソンのシリアル化:空の値(またはnull)を無視する


138

現在、Jackson 2.1.4を使用していますが、オブジェクトをJSON文字列に変換するときにフィールドを無視するのに問題があります。

これは、変換されるオブジェクトとして機能する私のクラスです:

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

そして、これが私がそれを変換する方法です:

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

出力は次のとおりです。

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

これらのnull値を回避するにはどうすればよいですか?必要な情報だけを「サブスクリプション」の目的で受け取りたい!

これが私が探している出力です:

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

@JsonInclude(Include.NON_NULL)も試し、すべての変数をnullに設定しましたが、機能しませんでした!助けてくれてありがとう!


回答:


247

あなたは間違った場所に注釈を持っています-それはフィールドではなくクラスにある必要があります。つまり:

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

コメントに記載されているように、2.xより前のバージョンでは、この注釈の構文は次のとおりです。

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

もう1つのオプションは、ObjectMapper直接呼び出すだけです。 mapper.setSerializationInclusion(Include.NON_NULL);

(記録としては、この回答の人気は、この注釈フィールドごとのベースである@fasterxmlに適用可能であることを示していると思います)


include.NON_NULLアノテーションを機能させる方法は本当にありませんか?それともNON_EMTPYですか?どれがnullになるかはわかっていますが、状況によって異なります。シリアル化/逆シリアル化するすべてのオブジェクトに同じ「JsonOperation」クラスを使用しており、状況に応じて使用する必要がある変数のみを初期化しています。これはそれを行うには良い方法であるか、私は変数のみそのIの必要性を含むseveralsクラス(ヌル/空の変数があることはありませんので、方法は、私は、任意のアノテーションを使用する必要がないことを)行う必要があります
Shinnyx

26
構文は最新バージョンで@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)および@JsonSerialize(include = JsonSerialize.Inclusion.NON_EMPTYに変更されました。非nullと空でないの両方が必要な場合は、@ JsonSerialize(include = JsonSerializeを使用してください。 .Inclusion.NON_DEFAULT)
Maciej

1
クラスの前または機能する前に@JsonSerialize(include = Inclusion.NON_NULL)を使用してください...
swan

1
@drewmooreをもう一度確認して@JsonInclude(JsonSerialize.Inclusion.NON_NULL) ください。そうである 必要が@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)あります。また、古い方法です。したがって、「バージョン2.x +ではなく」「バージョン2.xより前」と
記述してください

2
2. +使用@JsonInclude(Include.NON_NULL)
Honghe.Wu

48

グローバルオプションを設定することもできます。

objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

15

また、使用してみることができます

@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)

2+(1.9.5)より前のバージョンのジャクソンを扱っている場合、私はそれをテストしましたが、クラスの上でこのアノテーションを簡単に使用できます。属性の指定ではなく、クラスのdeclerationのみ。


2
JsonIncludeの賛成で廃止されJsonSerializeの属性を含める
fd8s0

2
私が言ったように:2+(1.9.5)より前のバージョンのジャクソン
erhanasikoglu 2014年

特定のバージョン2.1.4に関する質問
fd8s0

14

追加する必要があります import com.fasterxml.jackson.annotation.JsonInclude;

追加

@JsonInclude(JsonInclude.Include.NON_NULL)

POJOの上に

POJOをネストしている場合

@JsonInclude(JsonInclude.Include.NON_NULL)

すべての値を追加する必要があります。

注:JAXRS(ジャージー)は、このシナリオ2.6以降を自動的に処理します。


古いorg.codehaus.jackson.annotateパッケージを使用するときに同様の機能はありますか?
pkran 2016年

はい、ゲッターメソッドの例private int idの上に追加できます。@JsonIgnore public int getId(){return id; }
vaquar khan 2016

1
既存の回答と同じ
カールリヒター


2

最近バージョン2.6.6で同様の問題が発生していました。

@JsonInclude(JsonInclude.Include.NON_NULL)

上記のアノテーションをファイルレベルまたはクラスレベルで使用すると、期待どおりに機能しませんでした。POJOは、アノテーションを適用する場所で変更可能でした。POJOの動作を不変に変更すると、注釈はその魔法のように機能しました。

このlibの新しいバージョンまたは以前のバージョンまで同様の動作があったかどうかはわかりませんが、2.6.6では、注釈が機能するために不変POJOが必要です。

objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

ObjectMapperにシリアル化の包含をグローバルレベルで直接設定するさまざまな回答で述べた上記のオプションも機能しますが、クラスまたはファイルレベルで制御することを好みます。

したがって、JSONのシリアル化中にすべてのnullフィールドを無視したい場合は、クラスレベルで注釈を使用しますが、クラスで無視するフィールドをいくつかだけにしたい場合は、それらの特定のフィールドで使用します。これにより、特定の応答の動作を変更したい場合に、読みやすく、メンテナンスが容易になります。


2

または、GSON [ https://code.google.com/p/google-gson/ ]を使用することもできます。これらのnullフィールドは自動的に削除されます。

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

出力:

{"isLoggedIn":false}

gson-2.2.4を使用しました


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.