将复杂的JSON导出为CSV

时间:2019-05-22 14:12:56

标签: python json python-3.x

我有一个要从API下载的JSON文件。 目前,我已经能够将其导出为JSON,并可以通过Excel Power Query准确地解析数据。

将数据除以Campaign IDS(在这种情况下只有两个),然后在所选期间的每一天中,有几个相关的不同指标。 例如,这些是几行(不完整的)行供您查看其工作原理。

campaignId  metadata.id  metrics.impressions   metrics.clicks
s00821idk   2019-05-19   12000293121           100
s00821idk   2019-05-18   12300223151           103

我曾尝试使用Excel来解析此数据,这违背了使用API​​的目的。 由于我是从Python导出的,因此请通过Excel运行它,然后将其放在Google表格中。

我想用Python进行所有转换,以便可以使用Google Sheets API并将其放在其中。

在下面的链接中,我提供了导出的JSON文件。 file

如果能以这种方式帮助我构造数据,将非常感谢。 非常感谢。

2 个答案:

答案 0 :(得分:0)

如前所述,您需要完全展平多个嵌套值,然后迭代以获得所需的内容。可以这样做,但是它很大(每个广告系列ID超过24,000列),因此需要2分钟来遍历您提供的整个内容。

import json
import pandas as pd
import re


with open('C:/data.json') as f:
    jsonObj = json.load(f)


def flatten_json(y):
    out = {}
    def flatten(x, name=''):
        if type(x) is dict:
            for a in x:
                flatten(x[a], name + a + '_')
        elif type(x) is list:
            i = 0
            for a in x:
                flatten(a, name + str(i) + '_')
                i += 1
        else:
            out[name[:-1]] = x
    flatten(y)
    return out


flat = flatten_json(jsonObj)

results = pd.DataFrame()
special_cols = []

columns_list = list(flat.keys())
for item in columns_list:
    try:
        row_idx = re.findall(r'\_(\d+)\_', item )[0]
    except:
        special_cols.append(item)
        continue
    column = re.findall(r'\_\d+\_(.*)', item )[0]
    column = column.replace('_', '')

    row_idx = int(row_idx)
    value = flat[item]

    results.loc[row_idx, column] = value


for item in special_cols:
    results[item] = flat[item]

results.to_csv('file.csv', index=False)

输出:

print (results)
                           campaignId  ... totalCampaigns
0  0081da282b2dbe8140508074366cac91ba  ...              2
1  00c03d801da285767a093d0b4d5188fb34  ...              2

[2 rows x 24533 columns]

答案 1 :(得分:0)

IIUC-以下方法如何?
遍历所有campaignResults,遍历所有results,并写出campaignIDmetadata.id以及(例如)metrics.impressions和{{1 }}每行:

metrics.clicks

结果:

import json
sep = '\t'
with open(jsonfile) as jsonin, open('j2c.csv', 'w') as f:
    j = json.load(jsonin)
    f.write(f'campaignId{sep}metadata.id{sep}metrics.impressions{sep}metrics.clicks\n')
    for cR in range(j['totalCampaigns']):
        for r in range(j['campaignResults'][cR]['totalResults']):
            f.write(j['campaignResults'][cR]['campaignId']+ sep)
            f.write(j['campaignResults'][cR]['results'][r]['metadata']['id']+ sep)
            f.write(str(j['campaignResults'][cR]['results'][r]['metrics']['impressions']) + sep)
            f.write(str(j['campaignResults'][cR]['results'][r]['metrics']['clicks']) + '\n')

我仍然不太清楚您要提取的数据是什么-仅具有类似日期的模式的值或仅具有特定日期的值?
除此之外,我还没有真正了解您的json文件的结构,因此我尝试创建一个打印出的树,这可能有助于获得更清晰的视图并更精确地提出问题:

# campaignId    metadata.id metrics.impressions metrics.clicks
# 0081da282b2dbe8140508074366cac91ba    2019-05-20  176430.0    59.0
# 0081da282b2dbe8140508074366cac91ba    2019-05-19  169031.0    59.0
# 0081da282b2dbe8140508074366cac91ba    2019-05-18  108777.0    62.0
# 0081da282b2dbe8140508074366cac91ba    2019-05-17  272088.0    60.0
# 0081da282b2dbe8140508074366cac91ba    2019-05-16  198100.0    62.0
# ...
# 00c03d801da285767a093d0b4d5188fb34    2018-01-10  0.0 0.0
# 00c03d801da285767a093d0b4d5188fb34    2018-01-09  0.0 0.0
# 00c03d801da285767a093d0b4d5188fb34    2018-01-08  0.0 0.0
# 00c03d801da285767a093d0b4d5188fb34    2018-01-07  0.0 0.0
# 00c03d801da285767a093d0b4d5188fb34    2018-01-06  0.0 0.0

结果:

with open(file) as f:
    j = json.load(f)

def getStructure(dct, ind=''):
    indsym = '.\t'
    for k, v in dct.items():
        if type(v) is list:
            print(f'{ind}{k}[{len(v)}]')
            getStructure(v[0], ind + indsym)
        elif type(v) is dict:
            print(f'{ind}{k}')
            getStructure(v, ind + indsym)
        else:
            print(f'{ind}{k}')

getStructure(j)

这里有一个小问题:我认为相似列表元素中并不总是有相同的键:

# campaignResults[2]
# .       campaignId
# .       results[500]
# .       .       metadata
# .       .       .       id
# .       .       .       fromDate
# .       .       .       toDate
# .       .       .       lastCappingTime
# .       .       metrics
# .       .       .       impressions
# .       .       .       clicks
# .       .       .       conversions
# .       .       .       spend
# .       .       .       ecpc
# .       .       .       ctr
# .       .       .       conversionRate
# .       .       .       cpa
# .       .       .       totalValue
# .       .       .       averageValue
# .       .       .       conversionMetrics[6]
# .       .       .       .       name
# .       .       .       .       conversions
# .       .       .       .       conversionRate
# .       .       .       .       cpa
# .       .       .       .       totalValue
# .       .       .       .       averageValue
# .       totalResults
# totalCampaigns

因此请注意,上面的j['campaignResults'][0]['results'][0]['metadata'].keys() # dict_keys(['id', 'fromDate', 'toDate', 'lastCappingTime']) j['campaignResults'][1]['results'][0]['metadata'].keys() # dict_keys(['id', 'fromDate', 'toDate']) 函数仅查看列表的第一个元素以获取该列表的结构。