在Python中,当使用boto3从Dynamo DB检索项目时,会获得如下的模式。
{
"ACTIVE": {
"BOOL": true
},
"CRC": {
"N": "-1600155180"
},
"ID": {
"S": "bewfv43843b"
},
"params": {
"M": {
"customer": {
"S": "TEST"
},
"index": {
"N": "1"
}
}
},
"THIS_STATUS": {
"N": "10"
},
"TYPE": {
"N": "22"
}
}
同样在插入或扫描时,必须以这种方式转换字典。我无法找到一个负责这种转换的包装器。由于显然boto3不支持这个,有没有比为它实现代码更好的选择?
答案 0 :(得分:25)
为了理解如何解决这个问题,重要的是要认识到boto3有两种基本操作模式:一种使用低级Client API,另一种使用更高级别的抽象,如{{3 }}。问题中显示的数据结构是低级API消耗/生成的示例,AWS CLI和dynamodb Web服务也使用该低级API。
要回答您的问题 - 如果您在使用boto3时可以专门使用 Table 这样的高级抽象,那么对于您来说,事情将会更加轻松,正如评论所暗示的那样。然后你可以回避整个问题 - python类型与你的低级数据格式进行封送处理。
但是,有时候不可能只使用那些高级构造。在处理附加到Lambdas的DynamoDB流时,我特意遇到了这个问题。 lambda的输入始终采用低级格式,而且这种格式更难与IMO一起使用。
经过一番挖掘后,我发现boto3本身有一些漂亮的功能,可以进行转换。这些功能在前面提到的所有内部转换中隐式使用。要直接使用它们,请导入TypeDeserializer / TypeSerializer类并将它们与dict理解结合起来,如下所示:
import boto3
low_level_data = {
"ACTIVE": {
"BOOL": True
},
"CRC": {
"N": "-1600155180"
},
"ID": {
"S": "bewfv43843b"
},
"params": {
"M": {
"customer": {
"S": "TEST"
},
"index": {
"N": "1"
}
}
},
"THIS_STATUS": {
"N": "10"
},
"TYPE": {
"N": "22"
}
}
# Lazy-eval the dynamodb attribute (boto3 is dynamic!)
boto3.resource('dynamodb')
# To go from low-level format to python
deserializer = boto3.dynamodb.types.TypeDeserializer()
python_data = {k: deserializer.deserialize(v) for k,v in low_level_data.items()}
# To go from python to low-level format
serializer = boto3.dynamodb.types.TypeSerializer()
low_level_copy = {k: serializer.serialize(v) for k,v in python_data.items()}
assert low_level_data == low_level_copy
答案 1 :(得分:1)
有一个名为“dynamodb-json”的python包可以帮助您实现这一目标。 dynamodb-json util 的工作方式与 json 加载和转储功能相同。我更喜欢使用它,因为它负责转换 Decimal 对象。
您可以通过以下链接找到示例以及如何安装它 - https://pypi.org/project/dynamodb-json/
答案 2 :(得分:0)
您可以使用 TypeDeserializer 类
from boto3.dynamodb.types import TypeDeserializer
deserializer = TypeDeserializer()
document = { "ACTIVE": { "BOOL": True }, "CRC": { "N": "-1600155180" }, "ID": { "S": "bewfv43843b" }, "params": { "M": { "customer": { "S": "TEST" }, "index": { "N": "1" } } }, "THIS_STATUS": { "N": "10" }, "TYPE": { "N": "22" } }
deserialized_document = {k: deserializer.deserialize(v) for k, v in document.items()}
print(deserialized_document)