将数据转储到文件中时对字节数组进行解码和编码

问题描述 投票:0回答:1

下面是扫描DynamoDb表时得到的响应,如下所示。(数据的较短版本)。

{'id': {'S': '123'}, 'applicationName': {'S': 'swagger_petstore_1_0_0_mock_app'}, 'endpointIds': {'SS': ['hzl3ns24gzh6egwsltoaa7z4llvc3wq2']}, 'configDetails': {'S': '{"propertyPrefix":"","properties":[],"propertyOverrides":[]}'}, 'description': {'S': 'This is a sample server Petstore server.  You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/).  For this sample, you can use the api key `special-key` to test the authorization filters.'}, 'fullyQualifiedDockerImageUrl': {'S': 'R2-6-0.unified-managers.internal.tibco.com:5000/icyxmnf4ayukqsnylrs35spraggw3q27/4uv75dk6m6mg52xrezprwvq7w4x23i7t:1550829818352'}, 'lastModifiedBy': {'S': '3xxyd4szt62rop4npspdrihr5ufyjtwq'}, 'desiredInstanceCount': {'N': '1'}, 'appType': {'S': 'api-mock-app'}, 'version': {'S': '1.0'}, 'isSampleApp': {'N': '0'}, 'endpointBeansBytes': {'B': b'\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x00\xed[\xebo\xdb8\x12\xffW\x08\xef}\xb8\x05\x1c;\xaf\xb6@pw\xb8\xb4i\x0f\xc1v\xdb\xa0i\xee\xf6\x90\x04]F\xa2mn%Q!\xa98n\x90\xff\xfdf\x86\xd4\xc3\xb6$\xcbY\xa7M\x0f\xfd\x92X|\x0eg~\xf3\xe2\xe3\xfc\xae\'\xc3\xdeAo\xf2%|\x19\x03U\x15\xd2\xa1\xc1\x8f\x97N\xb2\xf2\xd2\t\xf8\xfe?\xa8\xb4CVa?\x00\x00'}}

为了在文件系统中写这个。

我做到了这一点。

with open("backup.json", "w+") as f:
                f.write(json.dumps(response, indent=JSON_INDENT, default=str))

请注意,我使用了默认解码方法(因为endpointBeansBytes不是json可序列化的)。

但是当我以这种方式加载这些数据时(尝试了几种方式):

1)json.load(open(backup.json))我能够读取endpointBeansBytes,但它与我们备份的数据不同。

2)使用此转换此数据。

endpointBeansBytes['B'] = str.encode(endpointBeansBytes['B'])仍然是不一样的数据。

3)endpointBeansBytes['B'] = endpointBeansBytes['B'].encode('utf-8')仍然是不一样的数据。

我的问题是,

1)json.dump默认使用什么解码方法?

2)为了编码步骤1中的数据,需要做什么?

3)我可以使用其他解码/编码而不是json.dump提供的默认值,这样就不会丢失数据的真实性。

json python-3.x
1个回答
0
投票

由于JSON不支持二进制数据,因此必须将二进制编码为字符串形式。在您的情况下,似乎二进制值由'B'键表示。

将二进制数据转换为字符串的常用方法是base64编码。

import json, base64, copy

response = {
    'id': {'S': '123'}, 
    'desiredInstanceCount': {'N': '1'},
    'isSampleApp': {'N': '0'},
    'endpointBeansBytes': {'B': b'\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x00\xed...'}
}

# --- saving ---------------------------------------------------------------
backup = copy.deepcopy(response)

for val in backup.values():
    if list(val)[0] == 'B':
        val['B'] = base64.b64encode(val['B']).decode('ascii')

with open("backup.json", "w+") as f:
    json.dump(backup, f, indent=2)

# --- restoring ------------------------------------------------------------
with open("backup.json", "r") as f:
    restore = json.load(f)

for val in restore.values():
    if list(val)[0] == 'B':
        val['B'] = base64.b64decode(val['B'].encode('ascii'))

print(response)
print(restore)

笔记:

  • json.dump()json.load()直接写入/读取文件对象
  • base64.b64encode()仍然给你字节,但这些字节都在ASCII范围内,使用.decode('ascii')转换为字符串是安全的。
  • read是镜像操作 - 使用.encode('ascii')将base64字符串转换为字节,然后通过base64.b64decode()恢复原始字节。
  • 我正在使用deepcopy所以我不修改原始数据。
  • defaultjson.dump参数和自定义的JSONEncoder都不适合这项任务,因为那些必要的上下文(“只有一个名为'B'的键的对象”)不能被看到。他们只看到价值本身。它们适用于JSON编码,因为当输入值为bytes时很明显,但它们不适用于JSON解码,因为不明显哪个输入字符串应该是base64解码的,哪个输入字符串应该是左边的单独。换句话说,不能保证每个可以解码base64的字符串都要被解码。
© www.soinside.com 2019 - 2024. All rights reserved.