概要
AWSでLambdaからDynamoDBを操作していると、jsonオブジェクトのfloat⇔Decimalの型変換が必要なタイミングが多々発生する。
ネストされたjsonの構造をいちいち調べて変換するのは大変であるため、一括での変換方法を作成してみた。
実行環境:Python 3.10
Decimal→floatの場合
こちらは検索でも何件かヒットした。
json.dumpsのdefaultを利用する。
import json
from decimal import Decimal
#Decimal->float,int変換用の関数を作成
def decimal_to_num(obj):
if isinstance(obj, Decimal):
return int(obj) if float(obj).is_integer() else float(obj)
#ネストされたDecimal型の要素を持つjsonを定義
json_decimal = {'key1': 'value1', 'key2': Decimal('12.3'), 'key3': {'key4': Decimal('456.7'), 'key5': 100, 'key6': [1, Decimal('8.9'), {'key7': Decimal('10.1')}]}}
#json.dumpsでstrに変換するタイミングでDecimalをfloatにする
json_str = json.dumps(json_decimal, default=decimal_to_num)
#jsonに戻す
json_float = json.loads(json_str)
#変換結果の出力。Decimal型はすべてfloat型になっている
print(json_float)
#print結果:{'key1': 'value1', 'key2': 12.3, 'key3': {'key4': 456.7, 'key5': 100, 'key6': [1, 8.9, {'key7': 10.1}]}}
float→Decimalの場合
こちらはあまり情報がなく難儀したが、公式ドキュメントに記載の通りjson.loadsのparse_floatを使って、floatをDecimalに変換可能。
import json
from decimal import Decimal
#ネストされたfloat型の要素を持つjsonを定義
json_float = {"key1": "value1", "key2": 12.3, "key3": {"key4": 456.7, "key5": 100, "key6": [1, 8.9, {"key7": 10.1}]}}
#一度strに変換
json_str = json.dumps(json_float)
#jsonに戻すタイミングでfloatをDecimalにする
json_decimal = json.loads(json_str, parse_float=Decimal)
#変換結果の出力。float型はすべてDecimal型になっている。intは影響なし。
print(json_decimal)
#print結果:{'key1': 'value1', 'key2': Decimal('12.3'), 'key3': {'key4': Decimal('456.7'), 'key5': 100, 'key6': [1, Decimal('8.9'), {'key7': Decimal('10.1')}]}}