web-dev-qa-db-ja.com

Pythonでboto3 Dynamo DBアイテムを通常の辞書に変換する方法は?

Pythonでは、boto3を使用してDynamo DBからアイテムを取得すると、次のようなスキーマが取得されます。

{
  "ACTIVE": {
    "BOOL": true
  },
  "CRC": {
    "N": "-1600155180"
  },
  "ID": {
    "S": "bewfv43843b"
  },
  "params": {
    "M": {
      "customer": {
        "S": "TEST"
      },
      "index": {
        "N": "1"
      }
    }
  },
  "THIS_STATUS": {
    "N": "10"
  },
  "TYPE": {
    "N": "22"
  }
}

また、挿入またはスキャンする場合、辞書はこの方法で変換する必要があります。このような変換を処理するラッパーを見つけることができませんでした。明らかにboto3はこれをサポートしていないので、コードを実装するよりも良い選択肢はありますか?

25
manelmc

これを解決する方法を理解するには、boto3に2つの基本的な操作モードがあることを認識することが重要です。1つは低レベルの Client APIを使用するモードで、もう1つは次のような高レベルの抽象化を使用する 。質問に示されているデータ構造は、AWS CLIおよびdynamodbウェブサービスでも使用される低レベルAPIによって消費/生成されるものの例です。

あなたの質問に答えるために-boto3を使用するときにTableのような高レベルの抽象化だけで作業できる場合、物事はかなり簡単になります、コメントが示唆するように。次に、問題全体を回避できます-python型は低レベルのデータ形式との間でマーシャリングされます。

ただし、これらの高レベルの構成を排他的に使用できない場合があります。 LambdasにアタッチされたDynamoDBストリームを処理するときに、この問題に特に遭遇しました。ラムダへの入力は常に低レベル形式であり、その形式はIMOでの作業が困難です。

少し調べたところ、変換を行うためにboto3自体にいくつかの便利な機能が組み込まれていることがわかりました。これらの機能は、前述のすべての内部変換で暗黙的に使用されます。それらを直接使用するには、TypeDeserializer/TypeSerializerクラスをインポートし、次のようにdict内包と組み合わせます。

import boto3

low_level_data = {
  "ACTIVE": {
    "BOOL": True
  },
  "CRC": {
    "N": "-1600155180"
  },
  "ID": {
    "S": "bewfv43843b"
  },
  "params": {
    "M": {
      "customer": {
        "S": "TEST"
      },
      "index": {
        "N": "1"
      }
    }
  },
  "THIS_STATUS": {
    "N": "10"
  },
  "TYPE": {
    "N": "22"
  }
}

# Lazy-eval the dynamodb attribute (boto3 is dynamic!)
boto3.resource('dynamodb')

# To go from low-level format to python
deserializer = boto3.dynamodb.types.TypeDeserializer()
python_data = {k: deserializer.deserialize(v) for k,v in low_level_data.items()}

# To go from python to low-level format
serializer = boto3.dynamodb.types.TypeSerializer()
low_level_copy = {k: serializer.serialize(v) for k,v in python_data.items()}

assert low_level_data == low_level_copy
51
killthrush