python - 使用自定义编码器将带有 Decimal 键的 python 字典转换为 JSON

标签 python json python-3.x decimal

JSON 只允许字符串作为键。

下面的代码使用自定义 JSONEncoder 将 Decimal 值转换为字符串。

有没有一种方法可以指定将 Decimal 键转换为字符串的编码器?

import json
import decimal

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

d1 = {3: decimal.Decimal(50)}
print(json.dumps(d1, cls=DecimalEncoder))

d2 = {decimal.Decimal(50): 3}
json.dumps(d2, cls=DecimalEncoder)  # TypeError: keys must be a string

我正在使用 python3.6

注意:显然我可以遍历我的字典并将 Decimal 类型替换为字符串值,但我希望通过向编码器添加行为来找到更优雅的解决方案。

最佳答案

不,您不能 Hook 键的处理,您必须在编码之前转换它们。您可以使用递归处理程序来执行此操作,例如:

from functools import singledispatch

@singledispatch
def string_keys(obj):
    return obj

@string_keys.register(dict)
def _(d):
    return {str(k): string_keys(v) for k, v in d.items()}

@string_keys.register(list)
def _(l):
    return [string_keys(v) for v in l]

所有这些所做的就是递归地转换列表和字典的嵌套结构,其中所有键都被强制为字符串。

转换为 JSON 时使用它:

json_encoded = json.dumps(string_keys(data))

您也可以通过添加另一个注册表来扩展它以处理 Decimal 对象(在键之外):

@string_keys.register(Decimal)
def _(d):
    return str(d)

换一种方式有点棘手,除非您明确标记 Decimal 键(例如使用前缀),否则您无法轻易区分以字符串开头的键和 Decimal 值。您可以在此处使用 try/except 方法:

from functools import singledispatch

@singledispatch
def keys_to_decimal(obj):
    return obj

@keys_to_decimal.register(dict)
def _(d):
    def try_decimal(k):
        try:
            return Decimal(k)
        except ValueError:
            return k
    return {try_decimal(k): keys_to_decimal(v) for k, v in d.items()}

@keys_to_decimal.register(list)
def _(l):
    return [keys_to_decimal(v) for v in l]

演示:

>>> string_keys([{Decimal(0): 'foo'}])
[{'0': 'foo'}]
>>> keys_to_decimal(string_keys([{Decimal(0): 'foo'}]))
[{Decimal('0'): 'foo'}]

关于python - 使用自定义编码器将带有 Decimal 键的 python 字典转换为 JSON,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46703043/

相关文章:

java - Python 和 Java 在 RegEx 语法上的差异

Python:查找每个月的平均股票值(value)

java - jackson 多态性: Nested Subtypes

java - GSON - JsonSyntaxException - 第 7 行第 4 列的预期名称

python - Pygame 速度和碰撞问题

python - 导入父模块和子模块

Python 3 "virtualenv not recognized"

java - JSONObject 无法转换为 JSONArray、SimpleJSON

python - 异步 : keep multiple coroutines running

regex - python 正则表达式不使用\b 进行计算