- 技術 💻
Float types are not supportedの直し方|DynamoDB
TypeError: Float types are not supported. Use Decimal types instead. は、boto3 で DynamoDB に保存する値の中に、Python の小数(float)が入っていたときのエラーです。 DynamoDB の数値は、boto3 では int か decimal.Decimal で渡す決まりになっています。
table.put_item(Item={"id": "p1", "price": 1.5}) # ← TypeError
直し方は、小数を Decimal("1.5") にすることです。 文字列から作るのがポイントです。
from decimal import Decimal
table.put_item(Item={"id": "p1", "price": Decimal("1.5")}) # OK
そして、読み出した数値は Decimal で返ってくるので、そのまま json.dumps すると、今度は逆向きのエラーになります。
| エラー | いつ | 直し方 |
|---|---|---|
TypeError: Float types are not supported. Use Decimal types instead. |
保存するとき(float を渡した) | Decimal("1.5")、JSON なら json.loads(..., parse_float=Decimal) |
TypeError: Object of type Decimal is not JSON serializable |
読み出した値を json.dumps したとき |
json.dumps(item, default=...) で変換 |
Inexact: [<class 'decimal.Inexact'>, <class 'decimal.Rounded'>] |
Decimal(1.1) のように float から作った |
Decimal(str(1.1)) か Decimal("1.1") |
TypeError: Infinity and NaN not supported |
Decimal("NaN") を保存した |
保存前に値を確かめる |
確認環境:boto3 1.43.111・Python 3.11(Linux)。DynamoDB の代わりに moto 5.2.4 のモックを使いました。表のエラーは、どれも boto3 が DynamoDB へ送る前の変換で出たものです(確認日 2026年10月12日)。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Float types are not supportedの直し方|DynamoDB」
なぜ float は使えないのか:boto3 の型の対応表
boto3 のドキュメントの、Table リソースで使える Python の型と DynamoDB の型の対応表です。数値(N)になるのは int と decimal.Decimal だけで、float は入っていません。
| Python の型 | DynamoDB の型 |
|---|---|
str |
String(S) |
int |
Number(N) |
decimal.Decimal |
Number(N) |
bool |
Boolean(BOOL) |
None |
Null(NULL) |
list |
List(L) |
dict |
Map(M) |
set(文字列・数値・Binary) |
SS・NS・BS |
float は 2進数で近い値を持つので、1.1 が正確には 1.1 ではありません。そのまま送ると値がずれるため、boto3 は float を受け付けず、Decimal を求めます。
原因① 小数をそのまま入れた(入れ子も同じ)
一番上の項目だけでなく、Map(dict)や List の中の float でも同じエラーでした。
| 渡した Item | 結果 |
|---|---|
{"id": "p1", "price": 1.5} |
TypeError: Float types are not supported |
{"id": "p1", "spec": {"weight": 0.25}} |
TypeError(dict の中) |
{"id": "p1", "scores": [1, 2.5]} |
TypeError(list の中) |
{"id": "p1", "price": 1200}(int) |
保存できた |
{"id": "p2", "price": Decimal("1.1")} |
保存できた |
原因② JSON を json.loads してそのまま保存した
API の入力や S3 のファイルなど、JSON を json.loads すると、小数は float になります。 それをそのまま put_item すると、このエラーになりました。
body = '{"id":"p3","price":980.5,"spec":{"weight":0.25},"tags":["a"]}'
table.put_item(Item=json.loads(body)) # ← TypeError
table.put_item(Item=json.loads(body, parse_float=Decimal)) # OK
parse_float=Decimal を付けると、JSON の中の小数が、入れ子の中まで全部 Decimal になります。 1つずつ変換するより確実です。
原因③ Decimal(1.1) と書いた(float から作った)
Decimal(1.1) は、float の 1.1 を「そのまま正確に」Decimal にします。 そのため、次のような長い値になりました。
>>> Decimal(1.1)
Decimal('1.100000000000000088817841970012523233890533447265625')
>>> Decimal(str(1.1))
Decimal('1.1')
この値を保存すると、Float types ではなく別のエラーになりました。
decimal.Inexact: [<class 'decimal.Inexact'>, <class 'decimal.Rounded'>]
AWS のドキュメントには「数値は最大38桁の精度で、超えると例外になる」とあり、それを超える桁を丸めようとして止まったものです。float の変数を Decimal にするときは、Decimal(str(値)) と文字列を通します。
price = 1.1 # float で受け取った値
item = {"id": "p2", "price": Decimal(str(price))}
読み出すと Decimal で返ってくる
保存した Decimal("1.1") と 10(int)を get_item で読み出すと、どちらも Decimal で返ってきました。 整数で保存しても Decimal('10') です。
>>> table.get_item(Key={"id": "p2"})["Item"]
{'id': 'p2', 'price': Decimal('1.1'), 'stock': Decimal('10')}
これを json.dumps すると、逆向きのエラーになります。
TypeError: Object of type Decimal is not JSON serializable
直し方:default で変換する
json.dumps の default に、Decimal を数値に変える関数を渡します。 整数なら int、小数なら float にすると、JSON では元の見た目の数値になりました。
import json
from decimal import Decimal
def decimal_default(o):
if isinstance(o, Decimal):
return int(o) if o == o.to_integral_value() else float(o)
raise TypeError(f"Object of type {type(o).__name__} is not JSON serializable")
json.dumps(item, default=decimal_default, ensure_ascii=False)
# {"id": "p2", "price": 1.1, "stock": 10}
| 書き方 | 結果 | 向いている場面 |
|---|---|---|
default=decimal_default(上の関数) |
{"price": 1.1, "stock": 10} |
画面や API に数値で返す |
default=str |
{"price": "1.1", "stock": "10"} |
桁を落とさず文字列で渡したい(金額など) |
金額など、float にすると誤差が困る値は default=str で文字列にして渡すのが安全です。受け取る側と、数値か文字列かを決めておきます。
Lambda で返すときは、書き方で結果が違った
Lambda の Python ランタイム(AWS が公開しているランタイムクライアント awslambdaric 4.2.0)で、Decimal を含む dict を返すところを再現しました。
| ハンドラの戻り値 | 結果 |
|---|---|
return item(Decimal を含む dict をそのまま) |
成功。{"id": "p2", "price": 1.1, "stock": 10} に変換された |
return {"statusCode": 200, "body": json.dumps(item)} |
失敗。TypeError: Object of type Decimal is not JSON serializable |
ランタイムクライアントは、戻り値の Decimal を数値に変換して返していました。 一方、API Gateway 向けに body を文字列にしようとして自分で json.dumps すると、そこでエラーになります。API Gateway と組み合わせるときは、body を作る json.dumps に default を付けます。
def lambda_handler(event, context):
item = table.get_item(Key={"id": event["pathParameters"]["id"]})["Item"]
return {
"statusCode": 200,
"headers": {"Content-Type": "application/json"},
"body": json.dumps(item, default=decimal_default, ensure_ascii=False),
}
client と resource で、渡し方が違う
ここまでの話は、boto3.resource("dynamodb").Table(...)(resource)の場合です。 boto3.client("dynamodb")(client)では、型を自分で書く形になり、Python の値をそのまま渡すと別のエラーになりました。
client.get_item(TableName="Products", Key={"id": "p2"})
# ParamValidationError: Invalid type for parameter Key.id, value: p2, type: <class 'str'>, valid types: <class 'dict'>
client.get_item(TableName="Products", Key={"id": {"S": "p2"}})["Item"]
# {'id': {'S': 'p2'}, 'price': {'N': '1.1'}, 'stock': {'N': '10'}}
| resource(Table) | client | |
|---|---|---|
| 渡し方 | {"price": Decimal("1.1")} |
{"price": {"N": "1.1"}} |
| 返り値 | Decimal('1.1') |
{'N': '1.1'}(文字列) |
| float | TypeError: Float types are not supported | 数値は文字列で書くので起きない |
client と resource の違いは、関連記事「boto3 client・resource・sessionの違いと認証の優先順位」で扱っています。
よくある質問
Q. 全部 int にして保存すればいいですか。 A. 金額を「円」、重さを「グラム」のように整数の単位で持てるなら、int で保存すると Decimal の扱いが楽になります。読み出すと Decimal で返ってくる点は同じです。
Q. pandas の DataFrame から保存するときは?
A. pandas(3.0.6)の DataFrame を to_dict した値を変換すると、小数の列が float のため同じエラーになりました。json.loads(df.to_json(orient="records"), parse_float=Decimal) のように、JSON を通して Decimal にする方法があります。
Q. datetime も保存できません。
A. AWS のドキュメントでも、DynamoDB に日時の型は無く、ISO 8601 の文字列("2026-10-12T09:00:00Z")か、エポック秒の数値で持つ方法が紹介されています。エポック秒なら TTL(期限切れの項目の自動削除)にも使えます。json.dumps のエラーは、関連記事「datetime is not JSON serializableの直し方」で扱っています。
Q. 数値の範囲はありますか。
A. 有効桁数 38 桁まで、正の数は 1E-130 から 9.9999…E+125 までです。Decimal("1" + "0"*40) を保存しようとすると、decimal.Rounded で止まりました。DynamoDB の使い方全般は、関連記事「DynamoDBの使い方|AWS CLIとboto3のquery・scan」で扱っています。
まとめ
Float types are not supportedは、保存する値に float が入っていた。入れ子の中も対象- 小数は
Decimal("1.5")。JSON からならjson.loads(..., parse_float=Decimal) Decimal(1.1)は長い値になってInexact。float からはDecimal(str(値))- 読み出した数値は int でも Decimal。
json.dumpsはdefault=で変換 - Lambda は Decimal を返しても変換されたが、自分で
json.dumpsするbodyは要注意
参考・出典
確認日はいずれも 2026年10月12日です。
- Boto3 ドキュメント「DynamoDB customization reference」(Valid DynamoDB types):https://docs.aws.amazon.com/boto3/latest/reference/customizations/dynamodb.html
- Amazon DynamoDB デベロッパーガイド「Supported data types and naming rules」(Number):https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html
- Python ドキュメント「json」(parse_float・default):https://docs.python.org/3/library/json.html
- Python ドキュメント「decimal」:https://docs.python.org/3/library/decimal.html
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Float types are not supportedの直し方|DynamoDB」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。