Posted at

DynamoDB x Python / Decimal を登録する

More than 3 years have passed since last update.


JSON と Python のマッピング

JSON と Python の dict は以下のようにマッピングされている。

JSON
Python

object
dict

array
list

string
unicode

number (int)
int, long

number(real)
float

true
True

false
False

null
None

そのため、JSON を json.loads() でパースして、そのまま dynamo.put_item() で登録すると前述の型で登録される。この際に float 型があると下記のように怒られる。

Float types are not supported. Use Decimal types instead.

Python の float はそのままでは DynamoDB に登録できないのである。

代わりに Decimal で登録する必要がある。


Float ではなく Decimal として登録するには?

Float を Decimal にマッピングさせる必要がある。

例えば以下の様なデータを登録するとする。


json_data

{"Timestamp": "20160323T203501.000+0900", "x": -0.279938, "y": -0.754028, "z": -0.607758 }


JSON をパースする際に下記のように parse_float=decimal.Decimal をつければよい。

import json

import boto3
import decimal
#...省略
item = json.loads(json_data, parse_float=decimal.Decimal)
dynamo = boto3.resource('dynamodb').Table('ThisIsJustTest')
dynamo.put_item(Item = item)


補足

Python 公式にも記載されていたが、ぐぐってもすぐに情報が出なかったので記事にした。

https://docs.python.org/2/library/json.html#encoders-and-decoders


parse_float, if specified, will be called with the string of every JSON float to be decoded. By default, this is equivalent to float(num_str). This can be used to use another datatype or parser for JSON floats (e.g. decimal.Decimal).


json.loads(s[, encoding[, cls[, object_hook[, parse_float[, parse_int[, parse_constant[, object_pairs_hook[, **kw]]]]]]]])

AWS のドキュメントにもサラッとのっていた。

https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/gettingstartedguide/GettingStarted.Python.02.html


Decimal から戻すとき

以下のようなやり方紹介されている。

https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/gettingstartedguide/GettingStarted.Python.03.html

http://stackoverflow.com/questions/1960516/python-json-serialize-a-decimal-object