python - Dynamodb 返回项目的节点或字符串格式错误

标签 python python-3.x amazon-web-services amazon-dynamodb

我一直在 AWS 中尝试 DynamoDB,但发现它不适合我。在 AWS 工作期间,我将大量记录上传到系统,现在我尝试使用 Python 检索这些记录。我承认,我对 Python 完全陌生,我拼凑的内容来自互联网上找到的示例。我正在使用包含许多字段的 Office 365 审核日志,当我从 Dynamo 检索它们时,我发现十进制字段返回为 decimal('1')

{
  'ItemType': 'File',
  'SourceFileName': 'xxx',
  'UserKey': 'xxx',
  'RecordType': Decimal('6'),
  'UserId': 'xxx',
  'ClientIP': 'xxx',
  'CorrelationId': 'xxx',
  'ObjectId': 'xxx',
  'Version': Decimal('1'),
  'Site': 'xxx',
  'WebId': 'xxx',
  'SourceFileExtension': 'js',
  'SiteUrl': 'xxx',
  'Workload': 'SharePoint',
  'SourceRelativeUrl': 'xxx',
  'EventSource': 'SharePoint',
  'ListId': 'xxx',
  'OrganizationId': 'xxx',
  'Operation': 'FileAccessed',
  'UserAgent': 'xxx',
  'ListItemUniqueId': 'xxx',
  'CreationTime': '2019-07-26T21:54:45',
  'UserType': Decimal('0'),
  'Id': 'xxx',
  'CustomUniqueId': False
}

在故障排除中,我发现了这个方便的函数,可以将 Decimal('0') 转换为实际的小数

class DecimalEncoder(json.JSONEncoder):
    def default(self, o):

        if isinstance(o, decimal.Decimal):
            if o % 1 > 0:
                return float(o)
            else:
                return int(o)
        return super(DecimalEncoder, self).default(o)

这个函数被调用

response = table.scan(Limit=10)
for i in response['Items']:
    d = ast.literal_eval((json.dumps(i, cls=DecimalEncoder)))

在大多数情况下,这工作得很好,除非 i 有一个 bool 字段(如上面的示例)。然后我得到这个错误

malformed node or string: <_ast.Name object at 0x04B3F778>

据我对 Python 的理解,True 和 False 的 bool 值大写正确。我考虑添加 DecimalEncoder 默认方法,但这不会有太大作用,因为它实际上返回相同的值

elif isinstance(o,bool):
    return True if o else False

我确实发现通过删除 key ,我没有收到错误

if 'CustomUniqueId' in i:
    del i['CustomUniqueId']

但是,不想失去这个字段。我不知道如何解决这个问题。

最佳答案

问题是您正在将 Python 对象转换为 JSON 字符串(即 json.dumps 命令),然后尝试将该字符串解释为 Python 字典(ast.literal_eval 接受一个字符串并尝试将其作为 Python 代码运行)。

Python 字典看起来与 JSON 对象非常相似,但它们并不是 100% 兼容。在 JSON 中, bool 值表示为 truefalse,在 Python 中表示为 TrueFalse

解决这个问题的方法是使用 json.loads 读取 JSON 字符串并将其转换为 Python 等效项:

d = json.loads((json.dumps(i, cls=DecimalEncoder)))

话虽这么说,这似乎需要大量的循环/处理才能将 Decimal 类转换为 native float ,并且建议直接使用 Decimal 或转换为 float (即 float(d['RecordType'])) 如果您需要将它们传递给需要 float 的东西。

关于python - Dynamodb 返回项目的节点或字符串格式错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60289491/

相关文章:

python - 如何调用产生的函数(python 2.7)

用于支持 AWS API Gateway 上的 API KEY 的 Spring Boot Swagger 注释

Python 3 : Set namespace for dynamic classes

python - 读取各种不同编码的文件

python - 如何在 Python 中将带分数的字符串转换为 float

amazon-web-services - Kafka Connect 与 AWS Hadoop 实例的托管

python - PutItem AWS DynamoDB 的无效类型错误

python - Openpyxl - 从 Excel 文件中的所有工作表中删除格式

python - 是否有将 VB 转换为脚本语言的工具,例如Python 还是 ruby ?

python - 为什么 `a<b<c` 在 Python 中有效?