この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
よく訓練されたアップル信者、都元です。ガンガンいきますよ。
前回は、Spring BootでWebアプリを書きました。しかし、モバイルのバックエンドや、リッチなフロントエンドを持つアプリケーションに対しては、JSONをやり取りするようなAPIサーバを書く機会が増えていると思います。
現時点において、APIサーバの入出力フォーマットのデファクトスタンダードはJSONであると思います。先日までのサンプルアプリケーションbersesrkerは、GET /users
に対して下記のような text/plain
を返していました。
User(username=miyamoto, password=$2a$10$cPnF0sq.bCPHeGuzVagOgOmbe2spT1Uh1k9LyuS0jzb5F3Lm.9kEy),
User(username=yokota, password=$2a$10$nkvNPCb3Y1z/GSearD7s7OBdS9BoLBss3D4enbFQIgNJDvr0Xincm)
願わくば、下記のような application/json
を返すAPIを実装したいものです。
[
{
"username": "miyamoto",
"password": "$2a$10$cPnF0sq.bCPHeGuzVagOgOmbe2spT1Uh1k9LyuS0jzb5F3Lm.9kEy"
},
{
"username": "yokota",
"password": "$2a$10$nkvNPCb3Y1z/GSearD7s7OBdS9BoLBss3D4enbFQIgNJDvr0Xincm"
}
]
ハンドラメソッドで自作のクラスを返してみる
@RequestMapping(value = "/users", method = RequestMethod.GET)
@Transactional
@ResponseBody
public ResponseEntity<?> users() {
log.debug("users");
Iterable<User> users = userRepos.findAll();
return ResponseEntity.ok(users);
}
こんな風に何も考えずに、User
の集合を返すことによって、それが実現できたらいいよなぁ、って思いませんか。
でもUser
というクラスは自分で作ったものだし、どのようにJSONに変換すべきか判断が付かないのが一般的でしょう。どうせ、これじゃRuntimeExceptionが発生するんだろうという諦めと、もしかしたらSpring Bootならやってくれるかもしれない、という淡い期待を抱きながら、いざ実行。 → /diff
$ curl -s http://localhost:8080/users
[{"username":"miyamoto","password":"$2a$10$cPnF0sq.bCPHeGuzVagOgOmbe2spT1Uh1k9LyuS0jzb5F3Lm.9kEy"},{"username":"yokota","password":"$2a$10$nkvNPCb3Y1z/GSearD7s7OBdS9BoLBss3D4enbFQIgNJDvr0Xincm"}]
キタ━━━━(゚∀゚)━━━━!!
あっけなさ過ぎますね。
passwordフィールドは出力したくない問題
さて、パスワードはハッシュ化しているとは言え出力したくないですね。もう一工夫して、ここは隠してみましょう。
そもそもJavaオブジェクトをJSON形式に変換しているのはJacksonというライブラリです。Jacksonの基本的な使い方は、こう!
@Data
@AllArgsConstructor
@NoArgsConstructor
public class HogeBean {
String str;
int num;
boolean bool;
}
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
String json = objectMapper.writeValueAsString(new HogeBean("foo", 1, true));
System.out.println(json);
HogeBean obj = objectMapper.readValue(json, HogeBean.class);
System.out.println(obj);
}
結果は、こう!
{"str":"foo","num":1,"bool":true}
HogeBean(str=foo, num=1, bool=true)
あー、もうなんて直感的なんでしょうか。さらにJacksonには様々なアノテーションが用意されており、これらを活用することによってJSONとObject間の変換処理を柔軟に制御できます。下記にメジャーどころを挙げますが、その他にも色々あります。
@JsonAnyGetter
@JsonAnySetter
@JsonCreator
@JsonIgnore
@JsonInclude
@JsonProperty
この中でそれっぽい奴、、、@JsonIgnore
ですね。これを User#password
につけてみましょう。
public class User {
// (ry
@Getter
@Setter
@Column(name = "password")
@JsonIgnore
private String password;
}
$ curl -s http://localhost:8080/users | jq .
[
{
"username": "miyamoto"
},
{
"username": "yokota"
}
]
めでたし。
恒例の、動かしてみようのコーナー
$ git clone https://github.com/classmethod-aws/berserker.git
$ cd berserker
$ git checkout 13.0
$ ./gradlew bootRun
まぁ、いつもの感じでやってみてください。