(編集履歴を削除したかったので再投稿しました。)
目的
AWSのDynamoDBにデータをインポートする際のDynamoDB JSON形式をJavaで生成する方法を記載します。
なお、DynamoDB JSONについてはこちらを参照下さい。
作りたいJSONの例
以下に例を記載します。
tagとnamesは属性名(個人的に開発しているアプリケーション依存)です。
ItemとSとSSは、DynamoDBの書き方です。
{"Item":{"tag":{"S":"後三年の役"},"names":{"SS":["後三年合戦金沢資料館","平安の風わたる公園"]}}}
{"Item":{"tag":{"S":"備後国"},"names":{"SS":["神石牛","鞆の浦","三原城","比婆牛","びんご畳表","尾道"]}}}
{"Item":{"tag":{"S":"三原村"},"names":{"SS":["四万十かいどう"]}}}
{"Item":{"tag":{"S":"東海村"},"names":{"SS":["東海十二景"]}}}
形は
{"Item":{"属性名":{"型": "値"}}}な感じです。なお、全体をリスト([]で囲み、カンマでセパレト)にする必要は無いみたいです(つまり、JSONLに近い形)。
使いどころ
AWSのDynamoDBにインポートする際のフォーマットに「DynamoDB JSON」を選択で利用します。
注意
もしかすると「AWS SDK for Java」に本記事に記載するコードよりしっかりしたものがあるかもしれません(ご存知な方、ご教示頂ければ幸いです)。
動作確認環境
Java 17系
ソースコード
まず、型ごとに変換用のメソッドを作ります。
// 文字列用
static String toJsonForString(String name , String s) {
return String.format("\"%s\":{\"S\":\"%s\"}", name, s);
}
// コレクション用
static String toJsonForStringSetInner(String name , Collection<String> ss) {
return String.format("\"%s\":{\"SS\":[%s]}",
name,
ss.stream()
.map(s -> String.format("\"%s\"", s))
.reduce((s1, s2) -> s1 + "," + s2).get());
}
// List<String>用
static String toJsonForStringSet(String name , List<String> ss) {
return toJsonForStringSetInner(name, ss);
}
// Set<String>用
static String toJsonForStringSet(String name , Set<String> ss) {
return toJsonForStringSetInner(name, ss);
}
DynamoDB JSON化したいオブジェクト自体は、Mapで渡します。
型に応じて呼び出すメソッドを変えます。
public static String toJson(Map<String, Object> item) {
return String.format("{\"Item\":{%s}}", item.entrySet().stream()
.map(entry -> {
String ret = null;
String clzName = entry.getValue().getClass().getSimpleName();
if (clzName.contains("List"))
ret = toJsonForStringSet(entry.getKey(),(List<String>)entry.getValue());
if (clzName.contains("Set"))
ret = toJsonForStringSet(entry.getKey(), (Set<String>)entry.getValue());
if (clzName.equals("String"))
ret = toJsonForString(entry.getKey(), (String)entry.getValue());
if (ret == null)
System.err.println(clzName);
return ret;
})
.filter(Objects::nonNull)
.reduce((s1, s2) -> s1 + "," + s2)
.get());
}
なお、importは以下になります。
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
参考資料
-
項目の操作:Java
これは普通の(?)JSONしか出力できない感じでした。 - DynamoDB Mapper for Java でサポートされるデータ型
- DynamoDB 用の Amazon S3 のインポート形式