展平从网站检索的嵌套JSON,并在Python 3中写入CSV

时间:2019-01-07 17:58:00

标签: python json api csv

我们想从IMF网站获取数据并将其转储到csv文件中。使用IMF为此目的发布的API完成数据的获取。但是,检索到的json列表包含一个嵌套字典,该字典可能为空或具有不同数量的元素,具体取决于数据不为空的年份。 以下是为查明问题而创建的代码段。我们正在通过Jupyter Notebook使用python 3.6.5

我们尝试使用json_normalize,但是它只能将顶级转换为csv。 JSON的第二个元素包含一个嵌套的字典,这会导致不希望的输出。

import requests
from pandas.io.json import json_normalize
#url = 'http://dataservices.imf.org/REST/SDMX_JSON.svc/CompactData/IFS/A.AU..?startPeriod=2017&endPeriod=2019'
url = 'http://dataservices.imf.org/REST/SDMX_JSON.svc/CompactData/IFS/A.AU.FDSBT_XDC+GG_GEG_G01_XDC+FFSE_XDC.?startPeriod=2017&endPeriod=2019'
# Navigate to series in API-returned JSON data
json_raw = (requests.get(f'{url}').json()['CompactData']['DataSet']['Series'])

json_normalize(json_raw)

json_normalize的输出结果为(观察到包含嵌套字典数组的'Obs'引起了问题)

  @FREQ      @INDICATOR @REF_AREA @TIME_FORMAT @UNIT_MULT                                                                                              Obs  Obs.@OBS_VALUE Obs.@TIME_PERIOD
0     A        FFSE_XDC        AU          P1Y          6                                                                                              NaN  15750.23064215             2017
1     A  GG_GEG_G01_XDC        AU          P1Y          6  [{'@TIME_PERIOD': '2017', '@OBS_VALUE': '4168'}, {'@TIME_PERIOD': '2018', '@OBS_VALUE': '3443'}]            NaN              NaN
2     A       FDSBT_XDC        AU          P1Y          6                                                                                              NaN             NaN              NaN

我们希望得到如下结果,以便可以将结构化格式转储到csv

  @FREQ      @INDICATOR @REF_AREA @TIME_FORMAT @UNIT_MULT Obs.@OBS_VALUE_0 Obs.@TIME_PERIOD_0 Obs.@OBS_VALUE_1 Obs.@TIME_PERIOD_1
0     A        FFSE_XDC        AU          P1Y          6 15750.23064215                 2017              NaN                NaN
1     A  GG_GEG_G01_XDC        AU          P1Y          6 4168                           2017 3443                           2018
2     A       FDSBT_XDC        AU          P1Y          6              NaN                NaN              NaN                NaN

1 个答案:

答案 0 :(得分:0)

这可能会帮助

def get_details_in_csv(jsonData):
    csvio = io.StringIO()
    names = ['Account Number', 'Account Name', 'Region', 'SG', 'Inbound port', 'Inbound IP', 'Assessment']
    writer = csv.DictWriter(csvio, fieldnames=names)
    writer.writeheader()
    for security_group in jsonData['SecurityGroups']:
        groupId = security_group["GroupId"]
        for inboundEntry in security_group["InboundDetails"]:
            inboundPort = inboundEntry['port']
            inboundIP = inboundEntry['source']
            assessment = inboundEntry['assessment']
            writer.writerow({'Account Number': ACCOUNT_NUMBER, 'Account Name': ACCOUNT_NAME, 'Region': REGION,
                             'SG': groupId, 'Inbound port': inboundPort,
                             'Inbound IP': inboundIP, 'Assessment': assessment})

    response = csvio.getvalue()
    print(csvio.getvalue())
    csvio.close()
    return response