【问题标题】:Comma separator between JSON objects with json.dump带有 json.dump 的 JSON 对象之间的逗号分隔符
【发布时间】:2018-10-12 23:41:54
【问题描述】:

我正在摆弄输出一个包含目录中文件的某些属性的 json 文件。我的问题是,附加到文件时,每个对象之间没有分隔符。我可以在每个“f”之后添加一个逗号并删除最后一个,但这对我来说似乎是一个草率的工作。

import os
import os.path
import json

#Create and open file_data.txt and append 
with open('file_data.txt', 'a') as outfile:

    files = os.listdir(os.curdir)


    for f in files:

        extension = os.path.splitext(f)[1][1:]
        base = os.path.splitext(f)[0]
        name = f

        data = {
            "file_name" : name,
            "extension" : extension,
            "base_name" : base
                }

        json.dump(data, outfile)

这个输出:

{"file_name": "contributors.txt", "base_name": "contributors", "extension": "txt"}{"file_name": "read_files.py", "base_name": "read_files", "extension": "py"}{"file_name": "file_data.txt", "base_name": "file_data", "extension": "txt"}{"file_name": ".git", "base_name": ".git", "extension": ""}

我想要的是实际的 JSON:

{"file_name": "contributors.txt", "base_name": "contributors", "extension": "txt"},{"file_name": "read_files.py", "base_name": "read_files", "extension": "py"},{"file_name": "file_data.txt", "base_name": "file_data", "extension": "txt"}{"file_name": ".git", "base_name": ".git", "extension": ""}

【问题讨论】:

    标签: python json


    【解决方案1】:

    你得到的不是一个 JSON 对象,而是一个单独的 JSON 对象流。

    你想要的是仍然不是一个 JSON 对象,而是一个单独的 JSON 对象流,它们之间有逗号。这将不再是可解析的。*

    * JSON spec 很简单,可以手动解析,而且很明显,一个对象后跟另一个带有逗号的对象不匹配任何有效的产生式。


    如果您尝试创建 JSON 数组,您可以这样做。除非存在内存问题,否则显而易见的方法是构建一个 dicts 列表,然后一次性转储所有内容:

    output = []
    for f in files:
        # ...
        output.append(data)
    json.dump(output, outfile)
    

    如果内存是个问题,您有几个选择:

    • 对于快速而肮脏的解决方案,您可以通过手动编写 [,] 来伪造它。 (但请注意,在最后一个值之后有一个额外的尾随逗号是无效的 JSON,即使某些解码器会接受它。)
    • 您可以将循环包装在生成每个data 的生成器函数中,并扩展JSONEncoder 以将迭代器转换为数组。 (请注意,这实际上用作 the example in the docs,说明为什么以及如何扩展 JSONEncoder,尽管您可能想要编写更节省内存的实现。)
    • 您可以寻找具有某种内置迭代流式处理 API 的第三方 JSON 库。

    但是,值得考虑您正在尝试做什么。也许一个单独的 JSON 对象流实际上您正在尝试做的正确文件格式/协议/API。因为 JSON 是自定界的,所以没有理由在单独的值之间添加定界符。 (而且它甚至对健壮性没有多大帮助,除非您使用不会出现在整个实际 JSON 中的分隔符,就像 , 那样。)例如,您所拥有的正是 JSON -RPC 应该看起来像。如果您只是因为不知道如何解析这样的文件而要求不同的东西,那很容易。例如(为简单起见,使用字符串而不是文件):

    i = 0
    d = json.JSONDecoder()
    while True:
        try:
            obj, i = d.raw_decode(s, i)
        except ValueError:
            return
        yield obj
    

    【讨论】:

      【解决方案2】:

      我遇到了同样的问题,因为我不想将整个对象列表加载到内存中,因此我需要将 yield 对象放入文件中。 这是我的方法(但我认为这有点 hacky):

      json_begin = '{"objects":['
      json_end = ']}'
      
      with open('file_data.txt', 'a') as outfile:
         files = os.listdir(os.curdir)
      
         outfile.write(json_begin)
      
         for f in files:
      
             extension = os.path.splitext(f)[1][1:]
             base = os.path.splitext(f)[0]
             name = f
      
             data = {
                 "file_name" : name,
                 "extension" : extension,
                 "base_name" : base
             }
      
             json.dump(data, outfile)
             if f != files[-1]:
                 outfile.write(',')
      
         outfile.write(json_end)
      

      【讨论】:

      • 有点hacky,但正是我需要导入SQL Server!
      猜你喜欢
      • 2013-02-06
      • 2019-05-10
      • 1970-01-01
      • 2016-07-06
      • 2013-04-13
      • 2019-01-22
      • 1970-01-01
      • 2018-06-21
      相关资源
      最近更新 更多