将嵌入在列表(或字典)中的字节转换为str以与json.dumps一起使用

时间:2019-07-03 15:58:41

标签: python python-3.x

我有一个函数可以接收Python列表或字典,其中可能包含嵌套字节,需要在调用json.dumps之前将其转换为str。

该函数接收的数据结构不是众所周知的。它可以是一个列表,可以是嵌套结构,并且可以具有多种数据类型。如果只是将其传递为字节编码的字符串,则可以使用简单的encode()达到目的。

[n | n <- nodes, nodeId n == 0]

但是在这种情况下,我们收到的结构更加复杂(为简洁起见,我将回溯截断了)。

>>> foo = [b'dog', b'cat', b'cow']
>>> foo2 = [f.decode() for f in foo]
>>> foo2
['dog', 'cat', 'cow']`
>>> json.dumps(foo2)
'["dog", "cat", "cow"]'

想拥有一个可以接受任意Python结构(列表,字典等)并返回已解码所有字节的函数。

>>> foo = [[14, 3.5, b'Tom'], [18, -1.2, b'Larry'], [22, -1.7, b'Sue']]
>>> json.dumps(foo)
Traceback (most recent call last):
...
TypeError: Object of type 'bytes' is not JSON serializable

那么问题是,如何实现一个mydecoder函数,该函数可以接收具有不同类型的任意列表/字典(可能嵌套),并返回具有解码后的所有字节的相同结构?

2 个答案:

答案 0 :(得分:2)

您可以将json.JSONEncoder的子类传递给json.dumps,该子类可以处理将字节字符串化的特殊情况。这将使您避免处理json编码器已经非常好的嵌套结构和边缘情况。您只需告诉它看到bytes

时该怎么办

在这里,您只需要处理bytes并让默认编码器完成其余工作即可:

import json

class BytesDump(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, bytes):                   # deal with bytes
            return obj.decode() 
        return json.JSONEncoder.default(self, obj)   # everything else

foo = [{"key": b'value'}, [14, 3.5, b'Tom'], [18, -1.2, b'Larry'], [22, -1.7, 'Sue']]

json.dumps(foo, cls=BytesDump)

结果

'[{"key": "value"}, [14, 3.5, "Tom"], [18, -1.2, "Larry"], [22, -1.7, "Sue"]]'

答案 1 :(得分:0)

抱歉,第一次来得有点慢。以下是转换和返回的方法:

import json

foo = [[14, 3.5, b'Tom'], [18, -1.2, b'Larry'], [22, -1.7, b'Sue']]
print(foo)
# to save
foo = [[i, j, k.decode("utf-8") ] for i, j, k in foo]
json_str = json.dumps(foo)

# to reload
foo = json.loads(json_str)
foo = [[i, j, bytes(k, 'utf-8')] for i, j, k in foo]

print(foo)