今回は、プロジェクトメンバーから以下の相談がありましたので、メモしていきたいと思います。
前提
- Jacksonを利用していて特にカスタマイズしていない。
- フロントのマッピングモデルには「name」項目がある。
相談内容
A君:バックエンドから以下のクラスに値と詰めて、レスポンスとして返していますが、フロントのモデルにマッピングされないです。
public class Sample implements Serializable {
private String name;
・・・・・・・・
public String getName1() { return this.name; }
public void setName1(String name) { this.name = name; }
・・・・・・・・
}
解説
上記のサンプルは、短いのですぐ気づいた方もいらっしゃるかと思いますが、それはgetterの名前がgetName1となっており、フロントのname1にマッピングされ、nameとして参照しようとしてもできないからです。それでは詳しく見ていきましょう。
なぜこうなるのか?
- getterメソッド名が標準的なJava Beanの命名規則に従っていません。
- Jacksonは依然としてgetterメソッドを基準にJSONプロパティ名を決定します。
getName1()から’get’を削除し、最初の文字を小文字にすると「name1」になります。- フィールド名「name」とは一致しませんが、getterメソッド名から「name1」がJSONプロパティ名として使用されます。
結論
- Jacksonはデフォルトでgetterメソッドを優先してJSONプロパティ名を決定します。
- 標準的なJava Beanの命名規則(*1)に従う場合、フィールド名とJSONプロパティ名が一致します。
*1. 標準的なJava Beanの命名規則について
Java Beanの命名規則は、JavaBeansの仕様に基づいており、主にプロパティ(フィールド)とそれに対応するgetter/setterメソッドの命名に関するものです。以下に主要な規則を示します
- プロパティ(フィールド)の命名:
- 小文字で始まる。
- 複合語の場合は、2語目以降の最初の文字を大文字にする(キャメルケース)。
- 例:
firstName,lastName,emailAddress
- 例:
- getterメソッドの命名:
- “get” で始まる。
- その後にプロパティ名を付け、プロパティ名の最初の文字を大文字にする。
- 例:
getFirstName(),getLastName(),getEmailAddress()
- 例:
- setterメソッドの命名:
- “set” で始まる。
- その後にプロパティ名を付け、プロパティ名の最初の文字を大文字にする。
- 例:
setFirstName(String firstName),setLastName(String lastName)
- 例:
- booleanプロパティの特別規則:
- getterメソッドは “is” で始めることができる(”get” の代わりに)。 例:
isActive(),isEnabled() - ただし、setterメソッドは依然として “set” で始まる。 例:
setActive(boolean active)
- getterメソッドは “is” で始めることができる(”get” の代わりに)。 例:
- 読み取り専用プロパティ:
- getterメソッドのみを持ち、setterメソッドを持たない。
- 書き込み専用プロパティ:
- setterメソッドのみを持ち、getterメソッドを持たない(あまり一般的ではありません)。
これらの規則に従うことで、Java Beanは多くのフレームワークやライブラリ(Spring MVCやJacksonなど)と互換性を持ち、予測可能な動作をします。
getterメソッド名が標準的な規則に従わない場合、予期せぬJSONプロパティ名が生成される可能性があrルので、一貫性のあるAPIのためには、命名規則を遵守するか、必要に応じて@JsonPropertyアノテーションを使用して明示的にJSONプロパティ名を指定することをお勧めします。
最後に
当たり前のように、getterを作るとき自動生成を利用するか、「get+フィールド名」にしていたため、詳しい内容までわからなかったのですが、バグの原因や解決まで至る。また、なぜそうなるとかなどこの記事でまとめながら整理できました。
相談してくれてありがとうございます!
