Lagomのサービスの入出力にJSONを使用する

Lagomを試してみるシリーズ第4回です。今回はサービスの入力・出力としてJSONを使う方法を試してみました。

基本的にはサービスのRequestやResponseにJavaクラスを指定しておけば自動的にJacksonでJSONとのデシリアライズシリアライズを行ってくれるようです。

まずはリクエストを受け取るために以下のクラスを作成しました。Immutabesを使ったデータクラスです。@JsonDeserializeアノテーションでImmutablesで生成された具象クラスでデシリアライズするよう設定しています。

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.lightbend.lagom.javadsl.immutable.ImmutableStyle;
import org.immutables.value.Value;

@ImmutableStyle
@Value.Immutable
@JsonDeserialize(as = HelloRequest.class)
public interface AbstractHelloRequest {
  @Value.Parameter
  String area();
  @Value.Parameter
  String name();
}

レスポンスを返すためのクラスも同様に作成します。@JsonDeserializeの代わりに@JsonSerializeアノテーションを使用しています。

import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.lightbend.lagom.javadsl.immutable.ImmutableStyle;
import org.immutables.value.Value;

@ImmutableStyle
@Value.Immutable
@JsonSerialize(as = HelloResponse.class)
public interface AbstractHelloResponse {
    @Value.Parameter
    String message();
}

サービスの定義を以下のようにします。RequestとResponseのところにImmutablesで生成されるデータクラスの具象型を指定しています。

public interface HelloService extends Service {

  ServiceCall<NotUsed, HelloRequest, HelloResponse> hello();

  @Override
  default Descriptor descriptor() {
    // @formatter:off
    return named("helloservice").with(
        restCall(Method.GET, "/api/hello", hello())
    ).withAutoAcl(true);
    // @formatter:on
  }
}

サービスの実装はこんな感じ。

public class HelloServiceImpl implements HelloService {
  @Override
  public ServiceCall<NotUsed, HelloRequest, HelloResponse> hello() {
    return (id, request) -> {
      return completedFuture(HelloResponse.of(
        "Hello, " + request.name() + " in " + request.area() + "!"
      ));
    };
  }
}

動作確認してみます。

$ curl -i -H 'Content-Type: application/json' -XGET http://localhost:9000/api/hello -d '{"name": "Naoki", "area": "Japan"}'
HTTP/1.1 200 OK
Content-Length: 36
Content-Type: application/json; charset=utf-8
Date: Sat, 16 Apr 2016 17:04:18 GMT

{"message":"Hello, Naoki in Japan!"}

JSONの使用については特に難しいところはなさそうです。