You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

DynamoDB Binary类型数据反序列化报TypeError问题排查

问题描述

对DynamoDB数据执行反序列化操作时,使用如下代码:

import json
import base64
import decimal
from boto3.dynamodb.types import TypeDeserializer
from base64 import b64encode

class DecimalEncoder(json.JSONEncoder):
    def default(self, o):
        if isinstance(o, set):
            return list(o)
        if isinstance(o, decimal.Decimal):
            if o % 1 > 0:
                return float(o)
            else:
                return int(o)
        if isinstance(o, bytes):
            return b64encode(o).decode()        
        return super(DecimalEncoder, self).default(o)


def from_dynamodb_to_json(item):
    return {k: TypeDeserializer().deserialize(value=v) for k, v in item.items()}

## 转换逻辑代码
base64.b64encode((json.dumps(from_dynamodb_to_json(payload["dynamodb"]["NewImage"]), cls=DecimalEncoder) + '\n').encode("utf-8")).decode("utf-8")

代码运行时抛出类型错误,提示传入值必须为<class 'bytearray'>、<class 'bytes'>类型,错误栈如下:

[ERROR] TypeError: Value must be of the following types: <class 'bytearray'>, <class 'bytes'>.
Traceback (most recent call last):
  File "/var/task/lambda_function.py", line 60, in lambda_handler
    'data': base64.b64encode((json.dumps(from_dynamodb_to_json(payload["dynamodb"]["NewImage"]), cls=DecimalEncoder) + '\n').encode("utf-8")).decode("utf-8")
  File "/var/task/lambda_function.py", line 33, in from_dynamodb_to_json
    return {k: TypeDeserializer().deserialize(value=v) for k, v in item.items()}
  File "/var/task/lambda_function.py", line 33, in <dictcomp>
    return {k: TypeDeserializer().deserialize(value=v) for k, v in item.items()}
  File "/var/runtime/boto3/dynamodb/types.py", line 271, in deserialize
    return deserializer(value[dynamodb_type])
  File "/var/runtime/boto3/dynamodb/types.py", line 286, in _deserialize_b
    return Binary(value)
  File "/var/runtime/boto3/dynamodb/types.py", line 51, in __init__
    ', '.join([str(t) for t in BINARY_TYPES]))

触发报错的payload样例数据如下:

{'awsRegion': 'ap-south-1', 'eventID': 'd926b17c-33a7-4d05-b936-7f5d9cd36a52', 'eventName': 'INSERT', 'userIdentity': None, 'recordFormat': 'application/json', 'tableName': 'dev_bhuvi_de', 'dynamodb': {'ApproximateCreationDateTime': 1656405526550, 'Keys': {'id': {'N': '261'}}, 'NewImage': {'id': {'N': '261'}, 'NewValue': {'B': 'YkdsdWRYaG9hVzUwTG1OdmJRbz0='}}, 'SizeBytes': 32}, 'eventSource': 'aws:dynamodb'}

报错出现在boto3的TypeDeserializer处理二进制(B)类型字段的环节。

问题根因

DynamoDB Streams传递的事件数据中,二进制(B)类型字段的值是经过base64编码的字符串,但boto3原生TypeDeserializer的二进制反序列化逻辑,要求输入值必须是bytes/bytearray类型的原始字节对象,直接传入base64字符串会触发类型校验失败。

修复方案

自定义继承TypeDeserializer的反序列化类,重写二进制类型的处理逻辑:先将事件中拿到的base64字符串解码为bytes类型,再交给原生反序列化逻辑处理即可。
修复后的完整代码如下:

import json
import base64
import decimal
from boto3.dynamodb.types import TypeDeserializer, Binary
from base64 import b64encode, b64decode

class DecimalEncoder(json.JSONEncoder):
    def default(self, o):
        if isinstance(o, set):
            return list(o)
        if isinstance(o, decimal.Decimal):
            if o % 1 > 0:
                return float(o)
            else:
                return int(o)
        if isinstance(o, bytes):
            return b64encode(o).decode()        
        return super(DecimalEncoder, self).default(o)

# 自定义适配DynamoDB Streams数据格式的反序列化器
class StreamTypeDeserializer(TypeDeserializer):
    def _deserialize_b(self, value):
        # 兼容Streams传入的base64字符串格式二进制值
        if isinstance(value, str):
            value = b64decode(value)
        return Binary(value)

def from_dynamodb_to_json(item):
    return {k: StreamTypeDeserializer().deserialize(value=v) for k, v in item.items()}

# 原有转换逻辑无需修改
base64.b64encode((json.dumps(from_dynamodb_to_json(payload["dynamodb"]["NewImage"]), cls=DecimalEncoder) + '\n').encode("utf-8")).decode("utf-8")

修复后二进制字段会被正确反序列化为boto3的Binary对象,后续DecimalEncoder会自动将其转为base64字符串,可正常完成JSON序列化与后续base64编码操作,不会再抛出类型错误。


内容的提问来源于stack exchange,提问作者TheDataGuy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 16:30:43