【问题标题】:Python CSV to JSON W/ Array OutputPython CSV 到 JSON W/数组输出
【发布时间】:2017-01-05 08:07:00
【问题描述】:

我正在尝试从 CSV 中获取数据并将其放入 JSON 格式的顶级数组中。

目前我正在运行此代码:

import csv
import json

csvfile = open('music.csv', 'r')
jsonfile = open('file.json', 'w')

fieldnames = ("ID","Artist","Song", "Artist")
reader = csv.DictReader( csvfile, fieldnames)
for row in reader:
    json.dump(row, jsonfile)
    jsonfile.write('\n')

CSV 文件格式如下:

| 1 | Empire of the Sun | We Are The People | Walking on a Dream |
| 2 | M83 | Steve McQueen | Hurry Up We're Dreaming | 

位置 = 第 1 列:ID |第 2 栏:艺术家 |第 3 栏:歌曲 |第四栏:专辑

得到这个输出:

    {"Song": "Empire of the Sun", "ID": "1", "Artist": "Walking on a   Dream"}
    {"Song": "M83", "ID": "2", "Artist": "Hurry Up We're Dreaming"}

我正试图让它看起来像这样:

{             
    "Music": [

    {
        "id": 1,
        "Artist": "Empire of the Sun",
        "Name": "We are the People",
        "Album": "Walking on a Dream"
    },
    {
        "id": 2,
        "Artist": "M83",
        "Name": "Steve McQueen",
        "Album": "Hurry Up We're Dreaming"
    },
    ]
}

【问题讨论】:

  • 仅针对问题 1,为您的 DictReader 设置使用以下 sn-p:import collections ; reader = DictReader(csvfile, fieldnames, dict_class=collections.OrderedDict)
  • 2 & 3 不清楚。如果您希望其他人提供帮助,请指定预期输出。
  • 导入在开头进入您的导入,reader = 行是您的 DictReader 初始化的直接替代品。
  • 预期的输出是我说的第一件事
  • 当我把“导入收藏;”在顶部,并添加“reader = DictReader(csv..)”它说 reader = DictReader(csvfile, dict_class=collections.OrderedDict) NameError: name 'DictReader' is not defined

标签: python arrays json csv output


【解决方案1】:

Pandas 非常简单地解决了这个问题。首先读取文件

import pandas

df = pandas.read_csv('music.csv', names=("id","Artist","Song", "Album"))

现在您有一些选择。从中获取正确 json 文件的最快方法很简单

df.to_json('file.json', orient='records')

输出:

[{"id":1,"Artist":"Empire of the Sun","Song":"We Are The People","Album":"Walking on a Dream"},{"id":2,"Artist":"M83","Song":"Steve McQueen","Album":"Hurry Up We're Dreaming"}]

这并不能处理您希望它全部包含在“音乐”对象或字段顺序中的要求,但它确实具有简洁的好处。

要将输出包装在 Music 对象中,我们可以使用to_dict

import json
with open('file.json', 'w') as f:
    json.dump({'Music': df.to_dict(orient='records')}, f, indent=4)

输出:

{
    "Music": [
        {
            "id": 1,
            "Album": "Walking on a Dream",
            "Artist": "Empire of the Sun",
            "Song": "We Are The People"
        },
        {
            "id": 2,
            "Album": "Hurry Up We're Dreaming",
            "Artist": "M83",
            "Song": "Steve McQueen"
        }
    ]
}

我建议您重新考虑坚持字段的特定顺序,因为 JSON specification 明确指出“对象是 无序 一组名称/值对”(强调我的)。

【讨论】:

    【解决方案2】:

    好吧,这是未经测试的,但请尝试以下操作:

    import csv
    import json
    from collections import OrderedDict
    
    fieldnames = ("ID","Artist","Song", "Artist")
    
    entries = []
    #the with statement is better since it handles closing your file properly after usage.
    with open('music.csv', 'r') as csvfile:
        #python's standard dict is not guaranteeing any order, 
        #but if you write into an OrderedDict, order of write operations will be kept in output.
        reader = csv.DictReader(csvfile, fieldnames)
        for row in reader:
            entry = OrderedDict()
            for field in fieldnames:
                entry[field] = row[field]
            entries.append(entry)
    
    output = {
        "Music": entries
    }
    
    with open('file.json', 'w') as jsonfile:
        json.dump(output, jsonfile)
        jsonfile.write('\n')
    

    【讨论】:

    • Traceback(最近一次调用最后一次):文件“spotPy.py”,第 9 行,在 reader = csv.DictReader( csvfile, fieldnames, dict_class=collections.OrderedDict) File "/usr /local/Cellar/python/2.7.12/Frameworks/Python.framework/Versions/2.7/lib/python2.7/csv.py”,第 79 行,在 init self.reader = reader( f, dialect, *args, **kwds) TypeError: 'dict_class' is an invalid keyword argument for this function
    • 哎呀。抱歉,那是一些非标准的 DictReader,一会儿。
    • 请注意 OP 代码中存在fieldnames = ("ID","Artist","Song", "Artist") 的错误。这应该是fieldnames = ("ID","Artist","Song", "Album")
    【解决方案3】:

    您的逻辑顺序错误。 json 旨在将单个对象递归地转换为 JSON。因此,在调用 dumpdumps 之前,您应该始终考虑构建单个对象。

    先收集成一个数组:

    music = [r for r in reader]
    

    然后放到dict:

    result = {'Music': music}
    

    然后转储到 JSON:

    json.dump(result, jsonfile)
    

    或全部在一行中:

    json.dump({'Music': [r for r in reader]}, jsonfile)
    

    “有序”JSON

    如果您真的关心 JSON 中对象属性的顺序(即使您不应该这样做),则不应使用 DictReader。相反,请使用常规阅读器并自己创建OrderedDicts:

    from collections import OrderedDict
    
    ...
    
    reader = csv.Reader(csvfile)
    music = [OrderedDict(zip(fieldnames, r)) for r in reader]
    

    或再次在一行中:

    json.dump({'Music': [OrderedDict(zip(fieldnames, r)) for r in reader]}, jsonfile)
    

    其他

    另外,为您的文件使用上下文管理器以确保它们正确关闭:

    with open('music.csv', 'r') as csvfile, open('file.json', 'w') as jsonfile:
        # Rest of your code inside this block
    

    【讨论】:

      【解决方案4】:

      它没有按照我想要的顺序写入 JSON 文件

      csv.DictReader 类返回 Python dict 对象。 Python 字典是无序的集合。您无法控制他们的演示顺序。

      Python 确实提供了一个OrderedDict,如果你避免使用csv.DictReader(),你可以使用它。

      它完全跳过了歌曲名称。

      这是因为该文件并不是真正的 CSV 文件。特别是,每一行都以字段分隔符开始和结束。我们可以使用.strip("|") 来解决这个问题。

      我需要将所有这些数据输出到一个名为“音乐”的数组中

      那么程序需要创建一个以"Music"为key的dict。

      我需要在每个艺术家信息后加上逗号。在我得到的输出中,我得到了

      这个问题是因为你多次调用json.dumps()。如果你想要一个有效的 JSON 文件,你应该只调用一次。

      试试这个:

      import csv
      import json
      from collections import OrderedDict
      
      
      def MyDictReader(fp, fieldnames):
          fp = (x.strip().strip('|').strip() for x in fp)
          reader = csv.reader(fp, delimiter="|")
          reader = ([field.strip() for field in row] for row in reader)
          dict_reader = (OrderedDict(zip(fieldnames, row)) for row in reader)
          return dict_reader
      
      csvfile = open('music.csv', 'r')
      jsonfile = open('file.json', 'w')
      fieldnames = ("ID","Artist","Song", "Album")
      reader = MyDictReader(csvfile, fieldnames)
      json.dump({"Music": list(reader)}, jsonfile, indent=2)
      

      【讨论】:

      • 你产生了一个标准的字典。那不是又丢订单了吗?
      • 不,订单已经销毁。每一行都已经是标准的dict
      • 是的,但请参阅我的回答 - 您可以通过按字段名的顺序将条目放入 OrderedDict 来强制它的顺序正确。
      • Traceback(最近一次调用最后):文件“spotPy.py”,第 15 行,在 json.dump({"Music": list(reader)}, jsonfile, indent=2 )文件“spotPy.py”,第 9 行,在 MyDictReader 中 yield {k:v.strip() for k,v in row.items()} 文件“spotPy.py”,第 9 行,在 中 yield {k :v.strip() for k,v in row.items()} AttributeError: 'NoneType' object has no attribute 'strip'
      • @AlwaysSunny - jpmc 的观点是Stack Overflow 并非旨在或设计为代码编写服务。它旨在成为有用信息的存储库。任何简单的“请为我编写代码”的问题对子孙后代都没有价值,事实上,人们更难找到真正的问题和答案。如果您的目标确实是让某人编写您的代码,那么还有其他网站专门为此目的而设计。
      猜你喜欢
      • 2021-12-21
      • 1970-01-01
      • 1970-01-01
      • 2011-07-02
      • 1970-01-01
      • 2017-07-22
      • 1970-01-01
      • 2019-07-02
      • 1970-01-01
      相关资源
      最近更新 更多