JacksonのアノテーションをGsonでも（どうしても）利用したい時の対処

[Jackson](https://github.com/FasterXML/jackson)も[GSON](https://github.com/google/gson)もJavaのオブジェクトとJSONを変換したいという要望に答えるものです。
Jacksonで使ってるアノテーションを、Gsonでも使いまわしたいという状況に（両方使うのがベストプラクティスではなさそうということは置いておいて）対処します。
この記事では、Java->JSONの変換、アノテーションは後述の2種類という条件に絞って記述します。

# Jacksonでのアノテーションの使われ方
Jacksonでは[@JsonProperty](https://www.javadoc.io/static/com.fasterxml.jackson.core/jackson-annotations/2.16.0/com/fasterxml/jackson/annotation/JsonProperty.html)や[@JsonIgnore](https://www.javadoc.io/static/com.fasterxml.jackson.core/jackson-annotations/2.16.0/com/fasterxml/jackson/annotation/JsonIgnore.html)等のアノテーションを使って、JSONのプロパティに付ける名前を変えたり、無視したりといったことを制御できます。

[例）プロパティの名前を変える](https://github.com/FasterXML/jackson-annotations#annotations-for-renaming-properties)
デフォルトで `{ "_first_name" : "Bob" }` というJSONに変換されるが、アノテーションがあるので `{ "firstName" : "Bob" }` になる。
```java
public class Name {
  @JsonProperty("firstName")
  public String _first_name;
}
```

同様に`@JsonIgnore`を付けたフィールドは変換の際に無視されます。


# GSONでストラテジーを定める
Gsonではフィールドの命名、無視を「ストラテジー」で定義します。
`@JsonProperty`と`@JsonIgnore`にそれぞれ、[ExclusionStrategy](https://www.javadoc.io/doc/com.google.code.gson/gson/latest/com.google.gson/com/google/gson/ExclusionStrategy.html)と[FieldNamingStrategy](https://javadoc.io/doc/com.google.code.gson/gson/latest/com.google.gson/com/google/gson/FieldNamingStrategy.html)が対応しています（[使用例](https://github.com/google/gson/blob/main/UserGuide.md#user-defined-exclusion-strategies)）。



ということで、アノテーションを読み込んでストラテジーを定義してやればいいのです（という案が[issue](https://github.com/google/gson/issues/1732#issuecomment-654904525)にありましたので、それを紹介しています）。

```Java
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](https://javadoc.io/doc/com.google.code.gson/gson/latest/com.google.gson/com/google/gson/annotations/SerializedName.html), [@Expose](https://javadoc.io/doc/com.google.code.gson/gson/latest/com.google.gson/com/google/gson/annotations/Expose.html)のアノテーションが用意されているので、完全にJacksonから移行できたらそちらを使いたいところです(`@Expose`は`@JsonIgnore`と逆の使い方なのでややこしいですが)。


# 参考
- [Jackson-Annotations](https://github.com/FasterXML/jackson-annotations) 
  - [docs](https://github.com/FasterXML/jackson-annotations/wiki)
- [Jackson-Databind](https://github.com/FasterXML/jackson-databind) 
  - [docs](https://github.com/FasterXML/jackson-databind/wiki)
- Gson https://github.com/google/gson
  - [javadoc](https://www.javadoc.io/doc/com.google.code.gson/gson/latest/com.google.gson/module-summary.html)
  - [UserGuide](https://github.com/google/gson/blob/main/UserGuide.md#gsons-expose)

GsonのNamingについて、ポリシーを設定することもできる-> https://github.com/google/gson/blob/main/UserGuide.md#json-field-naming-support