【问题标题】:writing a nested json into a csv using python使用python将嵌套的json写入csv
【发布时间】:2013-10-20 04:30:55
【问题描述】:

我在 python 中有一个以下 json 格式的文件:

{"header":{"a":"1","b":"1"}, 

"data":[{"a":"1", "b":{"ba":"b1","bb":"b2","bc":"b3"}, "c":{"ca":"x1","cb":"x2","cc":"x3"}, "d":"4"}, 

        {"a":"12", "b":{"ba":"12a","bb":"12ab","bc":"1ab"},"c":{"ca":"12z","cb":"12zz","cc":"12zzz"}, "d":"12"}
       ]}

我编写了一个没有嵌套“b”和“c”元素的 csv 解析器,但在尝试将“b”和“c”中的选定元素解析到我的 csv 时遇到了困难。这是我目前所拥有的:

#load json  
try:
    with open('tmp.p', 'rb') as f:
        myjson = json.load(f) 
except IOError:
    print("Error converting to json")

#write selected json to a csv output file      
out = open(savedpath, 'a+')
    try:
        #add or remove data to parse here    
        mydata = ('d','b','a')

        mycsv = csv.DictWriter(out, fieldnames=mydata, quoting=csv.QUOTE_ALL, extrasaction='ignore', lineterminator='\n')
        mycsv.writeheader()
        for row in myjson["data"]:
            mycsv.writerow(row)
    finally:
        out.close()

我已将嵌套元素解析为单独的临时文件:

# parse nested elements ##
try:
        #add or remove Port1/Port2 data to parse here
        myport = ('bb','ba')
        tmp3 = csv.DictWriter(t3, fieldnames=myport, quoting=csv.QUOTE_ALL, extrasaction='ignore', lineterminator='\n')
        tmp3.writeheader()
        tmp4 = csv.DictWriter(t4, fieldnames=myport, quoting=csv.QUOTE_ALL, extrasaction='ignore', lineterminator='\n')
        tmp4.writeheader()        
        #print myjson["data"][0]["b"]["bb"]
        #print myjson["data"][0]["c"]["bb"]

        for row in myjson["data"]:
            data1 = row["b"]
            data2 = row["c"]
            #print data1["bb"]

            tmp3.writerow(data1)
            tmp4.writerow(data2)
    finally:
        t3.close()
        t4.close()

但我在尝试加入数据时遇到了麻烦。我希望数据在我的 csv 中看起来像这样:

#header
a:1
b:1
#data
a,d,ba,bc,ca,cc
1,4,b1,b3,x1,x3
12,12,12a,1ab,12z,12zzz

我在尝试编写我的 csv 文件时卡住了。我想我想多了,但是因为我认为使用连接字符串可能会起作用,但它没有:

try:
        with open('tmp3.p', 'rb') as port1:
            with open('tmp4.p', 'rb') as port2:
                with open('tmp5.p', 'rb') as general:
                    for rport1 in port1:
                        for rport2 in port2:
                            for rgen in general:
                                rport1 = str.replace(rport1,"\n","")
                                rport2 = str.replace(rport2,"\n","")                        
                                rgen = str.replace(rgen,"\n","")                        
                                string = ("%s,%s,%s" % (rgen, rport1, rport2))
                                print string

我使用 DictWriter 是因为我需要按特定顺序解析文件。我知道我在尝试组合数据时违背了使用 json 的目的,这是一种非常糟糕的做法,但我不确定如何继续。提前感谢您的帮助...

【问题讨论】:

  • 附带说明,将所有内容缩进 7 层会使其更难阅读。除非您使用的是旧版本的 python,否则只需对所有三个文件使用单个 with,并查看是否可以简化循环或将它们分解为函数(可能都不合适,但值得尝试)..跨度>
  • 输出中的bbcb 列在哪里?
  • 如何将“b”和“c”元素的数据分别表示/格式化为一列?我能想到的唯一方法是作为一个字符串——但即便如此,它们应该以什么格式呈现在字符串中,json?
  • @abarnert,感谢您的回复。我正在使用 python 2.7,是的,我将更改为使用单行打开 3 个文件。循环的简化是问题所在。就我现在所拥有的,第一个 for 循环会用 n 个重复的第二个和第三个 for 循环进行迭代,依此类推......我不知道如何同步迭代每个文件并连接来自 n 行的字符串每个文件的。你有一个例子可以帮助我开始吗?
  • @lucemia,感谢您的回复。我不想将这些元素解析为 csv。我正在使用 DictWriter 的“忽略”来做到这一点。

标签: json csv python-2.7 nested


【解决方案1】:

我不是 100% 确定我明白你想要什么,但我想我可以从这条评论中猜到:

循环的简化是问题所在。就我现在所拥有的,第一个 for 循环会用 n 个重复的第二个和第三个 for 循环进行迭代,依此类推......我不知道如何同步迭代每个文件并连接来自 n 行的字符串每个文件。

你想要的不是嵌套迭代,而是 lockstep 迭代。换句话说,你不想要第一个rport1,每个rport2,然后是第二个rport1,每个rport2,依此类推;你想要第一个 rport1 和第一个 rport2,然后是第二个 rport1 和第二个 rport2,依此类推。

如果是这样,您正在寻找zip

我会用一个精简的例子来说明区别:

>>> seq1 = [1, 2, 3]
>>> seq2 = [4, 5, 6]
>>> 
>>> for i in seq1:
...     for j in seq2:
...         print i, j
1 4
1 5
1 6
2 4
2 5
2 6
3 4
3 5
3 6
>>> 
>>> for i, j in zip(seq1, seq2):
...     print i, j
1 4
2 5
3 6

【讨论】:

  • 太棒了,谢谢!!现在我有了一个可行的解决方案,这是解析具有以下要求的 json 文件的最佳实践吗:(1)仅解析选定的元素(包括嵌套元素),(2)以特定顺序显示选定的字段(不是按字母排序)?我当前的解决方案的顺序是(1)解析标头,(2)将选定的“数据”元素存储在 tmp 文件中(参考我上面的 sn-ps),(3)将选定的嵌套“b”和“c”元素存储到另一个tmp 文件,(4)打开 tmp 文件,将选定的“数据”级和嵌套元素加入并写入输出文件,(5)删除所有 tmp 文件。
  • @user2793334:通常情况下,对 JSON 文件的最佳处理是使用 json.load 解析整个内容,然后将其作为 Python 对象分离,而不是尝试手动解析 JSON 的部分内容.有时这是不合适的(例如,你有一个 1GB 的 JSON 文件,或者它不是很有效的 JSON,因为它在一个对象中具有重复的键或取决于排序),但从简单的方法开始,除非你知道它不会工作.
  • 知道了。我在脚本的开头编写了一个函数来验证我的 JSON 格式。 JSON 将上传到数据库,我使用相同的 JSON 来为非技术人员操作输出 csv 文件。谢谢你:)
猜你喜欢
  • 1970-01-01
  • 2018-08-10
  • 2015-06-06
  • 1970-01-01
  • 2013-12-23
  • 2021-08-15
  • 1970-01-01
  • 2020-08-02
  • 2018-08-29
相关资源
最近更新 更多