下面是我在扫描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
提供的默认解码/编码,以便不丢失数据的真实性。
答案 0 :(得分: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()
still 会为您提供字节,但是这些字节都在ASCII范围内,可以安全地使用.decode('ascii')
转换为字符串。.encode('ascii')
将base64字符串转换为字节,然后通过base64.b64decode()
恢复原始字节。deepcopy
,所以我不会修改原始数据。default
的{{1}}参数或自定义json.dump
都不适合此任务,因为它是必要的上下文(“对象只有一个名为{{ 1}}“ )不能被那些人看到。他们只看到价值本身。它们适用于JSON编码,因为当输入值为JSONEncoder
时很明显,但是它们不适用于JSON解码,因为不清楚哪个输入字符串应该被base64解码,以及哪个输入字符串是应该一个人呆着。换句话说,不能保证将 base64可解码的每个字符串都解码。