【新機能】AWS SDK for PHPがAmazon DynamoDBのJSONサポートに対応しました

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、せーのです。今日はAWS SDK for PHPがバージョンアップしましたのでご紹介致します。

The DynamoDB Marshaler

新しい機能は2.7.7に「DynamoDB Marshaler」というクラスで実装されています。こちらは読んで字のごとくDynamoDBのitem形式のフォーマットでJSON形式のテキストとPHPのArray型の変換ができるようになるクラスです。例えばこんなJSONファイルがあるとします。

{
  "id": "5432c69300594",
  "name": {
    "first": "Jeremy",
    "middle": "C",
    "last": "Lindblom"
  },
  "age": 30,
  "phone_numbers": [
    {
      "type": "mobile",
      "number": "5555555555",
      "preferred": true
    },
    {
      "type": "home",
      "number": "5555555556",
      "preferred": false
    }
  ]
}

こちらはDynamoDBのitemに入るようなMap型[M]とList型[L]を表したJSONファイルとなります。こちらをMarshalerを使ってDynamoDBに取り込みます。

use Aws\DynamoDb\DynamoDbClient;
use Aws\DynamoDb\Marshaler;
 
$client = DynamoDbClient::factory(/* your config */);
$marshaler = new Marshaler();
$json = file_get_contents('/path/to/your/document.json');
 
$client->putItem([
    'TableName' => 'YourTable',
    'Item'      => $marshaler->marshalJson($json)
]);

簡単ですね。MarshalerクラスのmarshalJson()メソッドに突っ込むだけです。印象的にはjson_decode()のDynamo版、という感じですね。このItemパラメータを見てみると

[
    'id' => ['S' => '5432c69300594'],
    'name' => ['M' => [
        'first' => ['S' => 'Jeremy'],
        'middle' => ['S' => 'C'],
        'last' => ['S' => 'Lindblom'],
    ]],
    'age' => ['N' => '30'],
    'phone_numbers' => ['L' => [
        ['M' => [
            'type' => ['S' => 'mobile'],
            'number' => ['S' => '5555555555']
        ]],
        ['M' => [
            'type' => ['S' => 'home'],
            'number' => ['S' => '5555555556']
        ]],
    ]],
];

という感じになります。綺麗にArrayに入りました。ちなみにキーの[S]はString、[N]はNumericですね。この対応が入るまではこのSとかNとかをいちいち指定したJSONを作らないといけませんでしたが、これでようやくスッキリ!ですね。元のJSONに戻す時はunmarshalJson()メソッドを使用します。

$result = $client->getItem([
    'TableName' => 'YourTable',
    'Key'       => ['id' => ['S' => '5432c69300594']]
]);
$json = $marshaler->unmarshalJson($result['Item']);

うん、こちらもスッキリ!ですね。

Marshaling a Native PHP Array

次に通常のPHPのArray型をDynamoDBのデータ型に落としこんだり、元に戻したりしてみましょう。こちらはそれぞれmarshalItem()メソッド、unmarshalItem()メソッドで実装されています。

$data = [
    'id' => '5432c69300594',
    'name' => [
        'first'  => 'Jeremy',
        'middle' => 'C',
        'last'   => 'Lindblom',
    ],
    'age' => 30,
    'phone_numbers' => [
        [
            'type'      => 'mobile',
            'number'    => '5555555555',
            'preferred' => true
        ],
        [
            'type'      => 'home',
            'number'    => '5555555556',
            'preferred' => false
        ],
    ],
];
 
// Marshaling the data and putting an item.
$client->putItem([
    'TableName' => 'YourTable',
    'Item'      => $marshaler->marshalItem($data)
]);
 
// Getting and item and unmarshaling the data.
$result = $client->getItem([
    'TableName' => 'YourTable',
    'Key'       => ['id' => ['S' => '5432c69300594']]
]);
$data = $marshaler->unmarshalItem($result['Item']);

こちらは基本的にDynamoDbClient::formatAttributes()のアップグレードとなります。

注意事項

とこのように便利な機能が追加されたわけですが、注意して置かなければいけないこととしては「binary型[B]、set型[SS, NS, BS]には対応していない、ということです。こちらは型的にJSONに変換しづらい、ということがあるようです。こちらの型についてはバージョン3にて対応予定です。

非推奨クラス

今回のバージョンアップ対応にて同じようにArray型とDynamoDBItemの変換等をしていた

  • Aws\DynamoDb\DynamoDbClient::formatValue()
  • Aws\DynamoDb\DynamoDbClient::formatAttributes()
  • Aws\DynamoDb\DynamoDbClient\Model\Attribute
  • Aws\DynamoDb\DynamoDbClient\Model\Item
  • Aws\DynamoDb\DynamoDbClient\Iterator\ItemIterator

これらのクラスにつきましてはバージョン3にて削除が予定されています。こちらのクラスを使っている方は今回新しく入ったMarshaler()クラスに移行することをお勧めします。

まとめ

いかがでしたでしょうか。DynamoDBのJSON対応自体は去年の10月にできてたのですが、先ほどのデータ型の指定をしなきゃいけない等、なかなか使いにくいものでしたが、これでひとまず使えるものになったのではないでしょうか。一度使ってみてください。

参考サイト