no risk no life

技術、投資、時事など

Retrofit2+GsonでJsonのint型で返却される真偽値をPOJOでboolean型に置き換える

発端

SerializedNameアノテーションを書いてもFieldNamePolicyを設定してもオブジェクトが正しく変換されなかった。

Jacksonに変えてもうまくいかない…。

と思ったらintで返却されている真偽値を、javaPOJOでbooleanを指定していた。

フィールドをintにしたら動いたが、気持ち悪いのでGsonでよしなにしてもらう。

gradle

...

    // network library
    compile 'com.squareup.retrofit2:retrofit:2.3.0'
    compile 'com.squareup.retrofit2:converter-gson:2.3.0'
    compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
    compile 'com.squareup.okhttp3:okhttp:3.9.0'
    compile 'com.squareup.okhttp3:logging-interceptor:3.9.0'

    // Rx
    compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
    compile 'io.reactivex.rxjava2:rxjava:2.1.3'

    // gson
    compile 'com.google.code.gson:gson:2.8.2'

...

Retrofit

public class ApiClient {
    static private Context mContext;
    static private Retrofit retrofit;

    public static void init(Context context){
        mContext = context;

        OkHttpClient httpClient = new OkHttpClient.Builder()
                .addNetworkInterceptor(new HttpLoggingInterceptor().setLevel(BuildConfig.DEBUG ? HttpLoggingInterceptor.Level.BODY : HttpLoggingInterceptor.Level.NONE))
                .addInterceptor(new AppCustomInterceptor())
                .addInterceptor(new AddCookiesInterceptor())
                .addInterceptor(new ReceivedCookiesInterceptor())
                .readTimeout(30, SECONDS)
                .writeTimeout(30, SECONDS)
                .connectTimeout(30, SECONDS)
                .build();

        Gson gson = new GsonBuilder()
                .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
                .registerTypeAdapter(boolean.class, new BooleanTypeAdapter())
                .create();

        retrofit = new Retrofit.Builder()
                .client(httpClient)
                .baseUrl(BuildConfig.API_ENDPOINT)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();
    }

    public static <V> V getApi(Class<V> clazz){
        return retrofit.create(clazz);
    }

}

BooleanTypeAdapter

public class BooleanTypeAdapter implements JsonDeserializer<Boolean>
{
    public Boolean deserialize(JsonElement json, Type typeOfT,
                               JsonDeserializationContext context) throws JsonParseException
    {
        int code = json.getAsInt();
        return code == 0;
    }
}

を追加してGsonにregisterするだけ。

これでPOJO側でbooleanを指定していても勝手にintから変換してくれる。