下面是扫描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不支持二进制数据,因此必须将二进制编码为字符串形式。在您的情况下,似乎二进制值由'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')
转换为字符串是安全的。.encode('ascii')
将base64字符串转换为字节,然后通过base64.b64decode()
恢复原始字节。deepcopy
所以我不修改原始数据。default
的json.dump
参数和自定义的JSONEncoder
都不适合这项任务,因为那些必要的上下文(“只有一个名为'B'
的键的对象”)不能被看到。他们只看到价值本身。它们适用于JSON编码,因为当输入值为bytes
时很明显,但它们不适用于JSON解码,因为不明显哪个输入字符串应该是base64解码的,哪个输入字符串应该是左边的单独。换句话说,不能保证每个可以解码base64的字符串都要被解码。