【问题标题】:Python json TypeError: Object of type Decimal is not JSON serializablePython json TypeError:Decimal 类型的对象不是 JSON 可序列化的
【发布时间】:2021-11-05 07:32:42
【问题描述】:

我确实检查了a lot of different related Q'n'A(请参阅链接问题),但没有一个解决我的具体问题,主要是关于不同的数据类型或要求。

尝试是使用这个sn-p将嵌套映射转换为json:

import json
#...
result = json.dumps(table_scan)

我知道the problems of this working correctly,但这似乎不是这里的问题。以上不幸给了我:

[ERROR] TypeError: Object of type Decimal is not JSON serializable
Traceback (most recent call last):
  File "/var/task/lambda-function.py", line 61, in lambda_handler
    result
  File "/var/lang/lib/python3.7/json/__init__.py", line 231, in dumps
    return _default_encoder.encode(obj)
  File "/var/lang/lib/python3.7/json/encoder.py", line 199, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/var/lang/lib/python3.7/json/encoder.py", line 257, in iterencode
    return _iterencode(o, 0)
  File "/var/lang/lib/python3.7/json/encoder.py", line 179, in default
    raise TypeError(f'Object of type {o.__class__.__name__} '

如何在不必进入(相当大的)地图进行“手动”转换的情况下解决此问题。

(更准确地说是应用程序上下文:我的 python AWS lambda 函数使用boto3 执行扫描 DynamoDB,这给了我一个(多层)dict≈map。我的目标是按顺序将此映射转换为 json将其(向外)返回到 AWS API 网关。数据库中的项目来自(向内)API 网关的事件参数。)

【问题讨论】:

    标签: python json python-3.x boto3


    【解决方案1】:

    很遗憾,我还不能将此作为评论发布。

    您可以考虑 monkey-patching 缺少功能 instead of writing your own JSONEncoder。为此,您可以(为简单起见)编写一个自己的小型独立模块,例如 make_json_serializable.py 以将此猴子补丁 (what is it?) 应用到

    json 模块在导入时,因此 JSONEncoder.default() 会自动检查特殊的“to_json()”方法,并在找到时使用它对对象进行编码。 (引用自here

    代码:

    from json import JSONEncoder
    
    def _default(self, obj):
        return getattr(obj.__class__, "to_json", _default.default)(obj)
    
    _default.default = JSONEncoder.default  # Save unmodified default.
    JSONEncoder.default = _default # Replace it.
    

    然后您可以将to_json 方法添加到任何类,例如取自this answer

    def to_json(self):
      return float(self) # or how you want it to be serialized
    

    那么您也不必更新项目like Onur said here 中的每个json.dumps()。应用这个猴子补丁应该像这样(未经测试):

    from decimal import Decimal
    Decimal.to_json = to_json
    

    【讨论】:

      【解决方案2】:

      特定 json 值(包括Decimal)的自定义编码器可用于as suggested here。在这个例子中,Decimal 大概应该被转换为float

      import json
      from decimal import Decimal
      
      #Does quasi the same things as json.loads from here: https://pypi.org/project/dynamodb-json/
      class JSONEncoder(json.JSONEncoder):
          def default(self, obj):
              if isinstance(obj, Decimal):
                  return float(obj)
              return json.JSONEncoder.default(self, obj)
      
      #...
      result = json.dumps(table_scan, cls=JSONEncoder)  #Works!
      

      【讨论】:

        猜你喜欢
        • 2021-03-26
        • 2021-09-24
        • 2020-11-18
        • 2021-04-29
        • 1970-01-01
        • 1970-01-01
        • 2018-11-27
        • 2019-07-12
        • 2021-07-04
        相关资源
        最近更新 更多