【问题标题】:How to create a list of JSON objects in Python 2.7如何在 Python 2.7 中创建 JSON 对象列表
【发布时间】:2014-09-15 19:53:21
【问题描述】:

我正在将 XML 文件转换为 JSON 文件。我通过打开 xml 来做到这一点,使用 xmltodict 模块,然后使用 .get 方法将树遍历到我想要的级别。这一层是叶子的父母。然后我在某个条件下检查每个task 的某些叶子是否为真,如果是,那么我使用json.dumps() 并将其写入文件。问题是(我认为这就是它的根源)当我只将一个 JSON 对象附加到文件时,它不会在对象末尾附加逗号,因为它认为它是唯一的对象。我尝试通过在每个 JSON 对象的末尾附加一个“,”来解决这个问题,但是当我尝试使用 json.loads() 方法时,它给了我一个错误,说“没有 JSON 对象可以被解码”。但是,当我手动将“[”和“]”附加到文件时,它不会给我一个错误。我的代码如下,如果您有任何帮助/建议,我将不胜感激。

def getTasks(filename):
    f = open(filename, 'r')
    a = open('tasksJSON', 'w')
    a.write('[')

    d = xmltodict.parse(f)
    l = d.get('Project').get('Tasks').get('Task')
    for task in l:
        if (task['Name'] == 'dinner'):  #criteria for desirable tasks
            j = json.dumps(task)
            a.write (str(j))   
            a.write(',')         

    a.write(']')
    f.close()
    a.close()

这有效,并将所有内容放在tasksJSON,但就像我说的,当我打电话时

my_file = open('tasksJSON', 'r')
data = json.load(my_file)           # LINE THAT GIVES ME ERROR

我收到一个错误提示

ValueError: No JSON object could be decoded

输出文件包含:

[{"UID": "4", "ID": "14", "Name": "Design"},{"UID": "5", "ID": "15", "Name": "Basic Skeleton"}]
                                           ^
                                 this is the comma I manually inserted

【问题讨论】:

  • 那不是你的输出文件。如果是,它会工作,@ 987654321@。您的代码生成的实际输出将在末尾有一个额外的逗号,这会给您一个错误as you can see here。

标签: python json python-2.7 dictionary


【解决方案1】:

这样做:

def getTasks(filename):
    f = open(filename, 'r')
    a = open('tasksJSON', 'w')
    x = []
    d = xmltodict.parse(f)
    l = d.get('Project').get('Tasks').get('Task')
    for task in l:
        if (task['Name'] == 'dinner'):  #criteria for desirable tasks
            #j = json.dumps(task)
            x.append(task)
            #a.write (str(j))   
            #a.write(',')         

    a.write(json.dumps(x))
    f.close()
    a.close()

【讨论】:

    【解决方案2】:

    JSON 不允许在数组或对象的末尾添加额外的逗号。但是您的代码添加了这样一个额外的逗号。如果你看官方的语法here,你只能在另一个value之前有一个,。而 Python 的 json 库符合该语法,所以:

    >>> json.loads('[1, 2, 3, ]')
    ValueError: Expecting value: line 1 column 8 (char 7)
    

    要解决此问题,您可以执行以下操作:

    first = True
    for task in l:
        if (task['Name'] == 'dinner'):  #criteria for desirable tasks
            if first:
                first = False
            else:
                a.write(',')
            j = json.dumps(task)
            a.write(str(j))   
    

    另一方面,如果内存不是问题,那么将所有对象添加到一个列表然后json.dumps该列表可能会更简单(当然也更干净):

    output = []
    for task in l:
        if (task['Name'] == 'dinner'):  #criteria for desirable tasks
            output.append(task)
    a.write(json.dumps(output))
    

    或者,更简单地说:

    json.dump([task for task in l if task['Name'] == 'dinner'], a)
    

    (事实上,即使内存是问题,你也可以扩展JSONEncoder,如the docs所示,通过将迭代器惰性转换为JSON数组来处理迭代器,但这是一个有点棘手,所以除非有人需要,否则我不会显示细节。)

    【讨论】:

    • 这是有道理的,谢谢@abarnet。但是,我仍然有点困惑。我将向您展示这段代码的输出文件是什么样子的。以上更新
    • @bagelboy:您发布的输出文件不是您真正的输出文件,并且不包含相同的问题,所以它当然可以工作。如果添加与实际输出文件相同的问题,则会得到相同的错误。有关更多详细信息,请参阅我对该问题的评论。
    【解决方案3】:

    看来,您将几个 json 对象放入一个文件并添加您自己的方括号。因此,它不能作为单个 obj 加载

    【讨论】:

    • JSON 只是字符串,一堆用逗号分隔并用括号括起来的有效 JSON 对象组成一个有效的 JSON 数组。
    猜你喜欢
    • 2020-06-07
    • 2017-05-23
    • 2022-11-05
    • 2014-07-17
    • 1970-01-01
    • 2010-09-25
    • 1970-01-01
    • 2012-11-07
    • 1970-01-01
    相关资源
    最近更新 更多