我编写了从文件中读取JSON的python脚本,对其进行转换,最后将修改后的JSON写入文件。我读过的JSON没有白色字符,因为我需要最小的尺寸。
问题是当我从文件中读取JSON并调用json.loads(json_content)
时,我得到dictionary
个对象,而python在键和值之间添加了空格。
文件中的JSON:
{"metadata":{"info":"important info"},"timestamp":"2018-04-06T12:19:38.611Z","content":{"id":"1","name":"name test","objects":[{"id":"1","url":"http://example.com","properties":[{"id":"1","value":"1"}]}]}}
我的剧本:
def get_contents_from_json(file_path):
with open(file_path) as file:
contents = file.read()
print(contents)
print(type(contents))
print(sys.getsizeof(contents))
print(len(contents))
return json.loads(contents)
if __name__ == '__main__':
data = get_contents_from_json(STACK_JSON)
print(data)
print(type(data))
print(sys.getsizeof(data))
string_data = json.dumps(data)
print(string_data)
print(type(string_data))
print(sys.getsizeof(string_data))
print(len(string_data))
trimmed = string_data.replace(" ", "")
print(contents)
print(type(trimmed))
print(sys.getsizeof(trimmed))
print(len(trimmed))
这段代码的输出是:
{"metadata":{"info":"important info"},"timestamp":"2018-04-06T12:19:38.611Z","content":{"id":"1","name":"name test","objects":[{"id":"1","url":"http://example.com","properties":[{"id":"1","value":"1"}]}]}}
<class 'str'>
255
206
{'metadata': {'info': 'important info'}, 'timestamp': '2018-04-06T12:19:38.611Z', 'content': {'id': '1', 'name': 'name test', 'objects': [{'id': '1', 'url': 'http://example.com', 'properties': [{'id': '1', 'value': '1'}]}]}}
<class 'dict'>
240
{"metadata": {"info": "important info"}, "timestamp": "2018-04-06T12:19:38.611Z", "content": {"id": "1", "name": "name test", "objects": [{"id": "1", "url": "http://example.com", "properties": [{"id": "1", "value": "1"}]}]}}
<class 'str'>
273
224
{"metadata":{"info":"importantinfo"},"timestamp":"2018-04-06T12:19:38.611Z","content":{"id":"1","name":"nametest","objects":[{"id":"1","url":"http://example.com","properties":[{"id":"1","value":"1"}]}]}}
<class 'str'>
252
203
说明:
Python从文件中读取JSON,作为文件中相同的字符串。 contents
的长度为206,大小为255,因为python中的空字符串有49个字节。
调用json.loads(contents)
返回大小为240的dict
对象。表示为dict
对象的JSON在键名和值之间添加了空格。这就是为什么调用string_data = json.dumps(data)
后string_data
的大小等于274且长度等于224的原因。因此,我尝试使用函数{{1}从string_data
中删除空格但是我忘记了一些值有空格,在这个操作之后JSON不正确。
我需要将JSON作为dict对象读取以方便转换,同时我必须保持最小的JSON大小。
有没有办法从.replace(" ", "")
对象中删除不必要的空格?
答案 0 :(得分:3)
您需要关注的是字符串的长度,因此请使用len()
来比较结果。
如果您关心生成的JSON大小,您可以轻而易举地告诉json.dumps()
不要使用任何空格:
string_data = json.dumps(data, separators=(',', ':'))
演示:
>>> import json
>>> sample = '''{"metadata":{"info":"important info"},"timestamp":"2018-04-06T12:19:38.611Z","content":{"id":"1","name":"name test","objects":[{"id":"1","url":"http://example.com","properties":[{"id":"1","value":"1"}]}]}}'''
>>> data = json.loads(sample)
>>> len(sample)
205
>>> len(json.dumps(data))
224
>>> len(json.dumps(data, separators=(',', ':')))
205
指定separators
后,输出长度与原始输入匹配。 separators
选项记录为:
如果指定,分隔符应该是
(item_separator, key_separator)
元组。如果缩进为(', ', ': ')
,则默认为None
,否则为(',', ': ')
。 要获得最紧凑的JSON表示,您应指定(',', ':')
以消除空格。
(大胆强调我的)。
sys.getsizeof()
是在这里进行比较的错误工具。该函数为您提供了对象的内存占用(无需递归),此内存占用量是当前Python实现和操作系统特定数据类型大小的实现细节。
dict
对象在您的操作系统上使用240个字节,但这是一个过度分配的引用哈希表。在具有不同大小指针的不同操作系统上,内存大小会有所不同,无论哪种方式,都不包括引用的字符串对象的大小。对于字符串对象,内存占用很大程度上取决于最高的Unicode代码点;字符串'a'
与''
的覆盖区不同,即使两者都有长度1,因为后者包含非BMP代码点,因此需要 4个字节来存储字符,加上Python对象开销。
接下来,你保存的只有19个空格。压缩会为你节省更多,压缩时空格并不重要:
>>> import zlib
>>> len(zlib.compress(json.dumps(data).encode('utf8'), 9))
155
>>> len(zlib.compress(json.dumps(data, separators=(',', ':')).encode('utf8'), 9))
154
压缩在那里保存了50个字节,而使用紧凑型JSON分隔符则保存了另一个字节。
答案 1 :(得分:2)
json.dumps
函数接受多个参数,这些参数允许您指定在将字典写回JSON字符串时希望数据格式化的方式。从它的文档字符串:
如果
indent
是非负整数,那么JSON数组元素和 对象成员将使用该缩进级别进行漂亮打印。缩进 等级0只会插入换行符。None
是最紧凑的 表示。如果已指定,则
separators
应为(item_separator, key_separator)
元组。如果缩进为(', ', ': ')
,则默认值为None
否则(',', ': ')
。要获得最紧凑的JSON表示, 你应该指定(',', ':')
来消除空格。
因此,请尝试string_data = json.dumps(data, indent=None, separators=(',', ':'))
以获得最紧凑的表示。