Java Lambda の入出力型を試してみた〜Map 編〜

Java Lambda の入出力の型には、いろんなパターンが使えます。

* Map 方式
* POJO 方式
* InputStream/OutputStream 方式

公式ドキュメントでは [ここ](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/java-handler.html#java-handler-types) に書かれています。

まずは、Map 方式から。

Lambda 関数に渡す入力 JSON はこれです。

```Json
{
    "name": "orange juice",
    "price": 1000,
    "releaseDate": 1601606387939,
    "rate": 4.5,
    "rawMaterial": ["orange", "fragrance"],
    "size": {
        "height": 10,
        "width": 20,
        "depth": 30
    }
}
```

以下のコードでは、この入力 JSON を Map として扱い、標準出力に書きつつ、同じく Map を使って別の JSON を出力しています。

```Java
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MapFunction implements RequestHandler<Map<String, Object>, Map<String, Object>> {
    @Override
    public Map<String, Object> handleRequest(Map<String, Object> event, Context context) {
        String name = (String) event.get("name");
        System.out.println(name); // orange juice

        Integer price = (Integer) event.get("price");
        System.out.println(price); // 1000

        Long releaseDate = (Long) event.get("releaseDate");
        System.out.println(releaseDate); // 1601606387939

        Double rate = (Double) event.get("rate");
        System.out.println(rate); // 4.5

        List<String> rawMaterial = (List<String>) event.get("rawMaterial");
        System.out.println(rawMaterial); // [orange, fragrance]

        Map<String, Integer> size = (Map<String, Integer>) event.get("size");
        Integer height = size.get("height");
        System.out.println(height); // 10

        Integer width = size.get("width");
        System.out.println(width); // 20

        Integer depth = size.get("depth");
        System.out.println(depth); // 30

        Map<String, Object> response = new HashMap<>();
        response.put("name", "coffee");
        response.put("price", Integer.valueOf(500));
        response.put("releaseDate", System.currentTimeMillis());
        response.put("rate", Double.valueOf(4.2));
        response.put("rawMaterial", Arrays.asList("coffee", "sugar"));

        Map<String, Integer> responseSize = new HashMap<>();
        responseSize.put("height", Integer.valueOf(100));
        responseSize.put("width", Integer.valueOf(200));
        responseSize.put("depth", Integer.valueOf(300));
        response.put("size", responseSize);

        return response;
    }
}
```

各値は、JSON の型に沿って　String、Integer、Long、Double に変換されてます。配列は List に、連想配列は Map に変換されます。

この Lambda 関数を実行すると、こんな JSON が出力されます。

```Json
{
  "size": {
    "depth": 300,
    "width": 200,
    "height": 100
  },
  "releaseDate": 1601615397265,
  "rate": 4.2,
  "price": 500,
  "rawMaterial": [
    "coffee",
    "sugar"
  ],
  "name": "coffee"
}
```

HashMap を使ってるので、順序はバラバラになります。HashMap ではなくて、たとえば TreeMap を使えば順序が維持されます。
ただ、この JSON を受け取る側が、順序に依存せずに解釈できる実装にする方が望ましいです。

このように、Java Lambda では、Map 型を使うことで JSON を扱うことができます。クラスを増やすことなくコードを書けるものの、キャストの嵐になってしまい、型セーフではなくなってしまいます。次の記事では、この問題を解決できる POJO 方式を紹介します。

Java Lambda の入出力型を試してみた〜POJO 編〜
https://qiita.com/kazfuku/items/095b4fb9c37638f57457