JacksonもGSONもJavaのオブジェクトとJSONを変換したいという要望に答えるものです。
Jacksonで使ってるアノテーションを、Gsonでも使いまわしたいという状況に(両方使うのがベストプラクティスではなさそうということは置いておいて)対処します。
この記事では、Java->JSONの変換、アノテーションは後述の2種類という条件に絞って記述します。
Jacksonでのアノテーションの使われ方
Jacksonでは@JsonPropertyや@JsonIgnore等のアノテーションを使って、JSONのプロパティに付ける名前を変えたり、無視したりといったことを制御できます。
例)プロパティの名前を変える
デフォルトで { "_first_name" : "Bob" }
というJSONに変換されるが、アノテーションがあるので { "firstName" : "Bob" }
になる。
public class Name {
@JsonProperty("firstName")
public String _first_name;
}
同様に@JsonIgnore
を付けたフィールドは変換の際に無視されます。
GSONでストラテジーを定める
Gsonではフィールドの命名、無視を「ストラテジー」で定義します。
@JsonProperty
と@JsonIgnore
にそれぞれ、ExclusionStrategyとFieldNamingStrategyが対応しています(使用例)。
ということで、アノテーションを読み込んでストラテジーを定義してやればいいのです(という案がissueにありましたので、それを紹介しています)。
GsonBuilder gb = new GsonBuilder()
// 命名方法を決める
.setFieldNamingStrategy(field -> {
final JsonProperty jp = field.getAnnotation(JsonProperty.class);
if (Objects.isNull(jp)) {
return FieldNamingPolicy.IDENTITY.translateName(field); // アノテーションない場合の命名方法
}
return jp.value(); // アノテーションの値をフィールド名に採用
})
// 無視するものを決める
.addSerializationExclusionStrategy(new ExclusionStrategy() {
@Override
public boolean shouldSkipField(FieldAttributes field) {
return Objects.nonNull(field.getAnnotation(JsonIgnore.class)); // フィールドにJsonIgnoreが設定されていたら無視
}
@Override
public boolean shouldSkipClass(Class<?> clazz) {
return Objects.nonNull(clazz.getAnnotation(JsonIgnore.class)); // クラス単位でも無視するかを決める(使ってない場合でもOverrideが必要(なはず))
}
});
ただし、Gsonにも@SerializedName, @Exposeのアノテーションが用意されているので、完全にJacksonから移行できたらそちらを使いたいところです(@Expose
は@JsonIgnore
と逆の使い方なのでややこしいですが)。
参考
GsonのNamingについて、ポリシーを設定することもできる-> https://github.com/google/gson/blob/main/UserGuide.md#json-field-naming-support