“Decimal”类型的对象不可 JSON 序列化:AWS Lambda - DynamoDB

问题描述 投票:0回答:4

由于客户函数错误,Lambda 执行失败,状态为 200:“Decimal”类型的对象不可 JSON 序列化

我浏览了以下链接中的所有现有解决方案,但没有任何效果对我有用。我做错了什么?: Python JSON 序列化 Decimal 对象

import json
import boto3
import decimal


client = boto3.resource('dynamodb')
table = client.Table('table')

def lambda_handler(event, context):
    method = event["httpMethod"]
    print(event)
    if method=="POST":
        return POST(event)
    elif method=="DELETE":
        return DELETE(event)
    elif method=="GET":
        return GET(event)

#the respons format
def send_respons(responseBody, statusCode):
    response = {
        "statusCode": statusCode,
        "headers": {
            "my_header": "my_value"
        },
        "body": json.dumps(responseBody),
        "isBase64Encoded": 'false'
    }
    return response
    

def GET(event):
    tab = table.scan()['Items']
    ids = []
            for item in tab:
                    ids.append({"id":item["id"], "decimalOBJ":decimal.Decimal(item["decimalOBJ"]}))
            return send_respons(ids, 201)
python json aws-lambda amazon-dynamodb json-serialization
4个回答
34
投票

这是扩展

JSONEncoder
来处理
Decimal
类型的示例,该类型也在 json 文档中指定

from decimal import Decimal

class DecimalEncoder(json.JSONEncoder):
  def default(self, obj):
    if isinstance(obj, Decimal):
      return str(obj)
    return json.JSONEncoder.default(self, obj)

使用调用它

json.dumps(some_object, cls=DecimalEncoder)

通过转换为

str
,将保持良好的精度,而不依赖于外部包。


17
投票

看来你有两个选择:

  1. 可能最简单,您可以序列化 Decimal 对象的 int/float 值:

""" assume d is your decimal object """

serializable_d = int(d) # or float(d)

d_json = json.dumps(d) 

  1. 您可以将 simplejson 添加到您的requirements.txt,它现在支持序列化小数。它是包含的 json 模块的直接替代品。
import simplejson as json # instead of import json

其余代码的工作方式相同。如果您需要进一步帮助,请发表评论。


6
投票

创建一个函数来处理

TypeError
并使用
default
json.dumps
参数来设置它。这样就避免了
TypeError: Object of type Decimal is not JSON serializable

https://docs.python.org/3/library/json.html

如果指定,默认值应该是一个被调用的函数 否则无法序列化的对象。它应该返回一个 JSON 对象的可编码版本或引发 TypeError。如果不 指定时,会引发 TypeError。

json_utils.py:

import decimal
import json


def dumps(item: dict) -> str:
    return json.dumps(item, default=default_type_error_handler)


def default_type_error_handler(obj):
    if isinstance(obj, decimal.Decimal):
        return int(obj)
    raise TypeError

test_json_utils.py:

import json
from decimal import Decimal
from commons import json_utils


def test_different_data_types():
    # Prepare data
    item = {
        "a-string": "lorem",
        "a-boolean": True,
        "a-number": 4711,
        "a-decimal-object": Decimal(4711)  # Used by dynamoDb boto3 client
    }

    # Execute
    item_as_json = json_utils.dumps(item)

    # Assert
    item_back_to_dict = json.loads(item_as_json)
    assert item_back_to_dict == item

0
投票

创建一个用于调整 JSON 编码的类似乎太多了,至少对于这种情况尤其如此。

使用

int
作为默认函数,
dumps
将显示为
int
,无法序列化的对象:

json.dumps(response, default=int)

有关该方法的更多信息描述于此处

© www.soinside.com 2019 - 2024. All rights reserved.