【问题标题】:Append the data to existing json file将数据附加到现有的 json 文件
【发布时间】:2016-08-25 13:01:01
【问题描述】:

我有一个现有的 JSON 文件并尝试将字符串添加到文件中。但是一旦我写了一个 JSON 文件,新行字符就会在 JSON 文件中消失并且格式会改变。

下面是代码:

#!/usr/bin/python
import json

userinput = raw_input('Enter the name of a file a you want to read: ')
with open(userinput) as json_data:
    s = json_data.read()
    data = json.loads(s)
    print data['classes']
json_data.close()


class_add = raw_input('Enter the name of a class a you want to add: ')
if class_add in data['classes']:
    print "Class %s already exists, doing nothing." % class_add
else:
    data['classes'].append(class_add)
    print json.dumps(data)
    print data['classes']
    with open(userinput, 'w') as json_data:
        json_data.write(json.dumps(data))
    json_data.close()

这里还有一个重要的事情是 JSON 文件的格式。因此,默认情况下,我们将拥有以下格式的文件。

# cat test.json
{
    "selinux_mode": "enforcing",
    "cis_manages_auditd_service": true,
    "classes": [ "basic", "admin", "lvm"]
}
#

但是一旦我们添加了这个类,它就会变成下面这样。

# cat test.json 
{"cis_manages_auditd_service": true, "classes": [ "basic", "admin", "lvm"], "selinux_mode": "enforcing"}

有什么方法可以让 JSON 空格和换行符保持原样而不改变任何内容。

【问题讨论】:

  • 你为什么叫json_data.close(),那个文件描述符在with语句的末尾关闭。
  • 不知道当我们使用 with 语句时它会自动关闭文件。从现在开始,我不会再使用它了。谢谢
  • 您无法将json.dumps() 的格式控制到您想要的程度。可以通过在调用中添加 indent=4 参数来提高输出的可读性。

标签: python json file-io


【解决方案1】:

JSON 不需要特定的布局,但为了稍微降低人类可读性,您可以提供 indent=2

import sys
import json

userinput = raw_input('Enter the name of a file a you want to read: ')
with open(userinput) as json_data:
    data = json.load(json_data)
    print(data['classes'])


class_add = raw_input('Enter the name of a class a you want to add: ')
if class_add in data['classes']:
    print("Class {} already exists, doing nothing.".format(class_add))
else:
    data['classes'].append(class_add)
    json.dump(data, sys.stdout, indent=2)
    print(data['classes'])
    with open(userinput, 'w') as json_data:
        json.dump(data, json_data, indent=2)

请注意,如果您使用with 语句打开文件,则不应显式关闭它(无论是否存在异常,都应在块的末尾完成)。

如果您正在写入文件,而不是将 JSON 作为字符串处理,您还应该避免使用 json.dumps(data) 并改用 json.dump(data, file_pointer)json.loads()json.load() 也是如此。

【讨论】:

  • 好的。让我尝试修改代码并重新运行以测试它。谢谢
  • 所以classes 节以长空格打印。有什么方法可以为其中的每个元素剪切换行符。
  • 我还有十个使用print 作为函数(print()),当你切换到 Python 3 时,你将不得不使用它,所以要习惯括号(并添加 from __future__ import print_function 到所有.py 文件的顶部)
  • 我不认为你对 JSON 有那么细粒度的控制。如果这都是关于可读性的,我会看 YAML 而不是使用 JSON。使用 ruamel.yaml(我是其作者),您可以保留布局和 cmets。
【解决方案2】:

您可以将函数json.dumps()indent 参数设置为表示要缩进的空格数的整数。

这仍然会将输出的格式修改为如下所示:

import json

s = '''{
    "selinux_mode": "enforcing",
    "cis_manages_auditd_service": true,
    "classes": [ "basic", "admin", "lvm"]
}'''

data = json.loads(s)

>>> print(json.dumps(data))
{"cis_manages_auditd_service": true, "classes": ["basic", "admin", "lvm"], "selinux_mode": "enforcing"}

>>> print(json.dumps(data, indent=4))
{
    "cis_manages_auditd_service": true, 
    "classes": [
        "basic", 
        "admin", 
        "lvm"
    ], 
    "selinux_mode": "enforcing"
}

原始版本和更新版本之间的区别在于classes 列表现在显示为多行。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多