将API文件中的JSON输出解析为CSV

时间:2016-09-13 21:28:03

标签: python json csv

我目前正在尝试将API请求的JSON输出转换为CSV格式,以便将结果存储到数据库中。这是我目前的参考代码:

import pyodbc
import csv
#import urllib2
import json
import collections
import requests
#import pprint
#import functools

print ("Connecting via ODBC")

conn = pyodbc.connect('DSN=DSN', autocommit=True)

print ("Connected!\n")

cur = conn.cursor() 

sql = """SELECT DATA"""

cur.execute(sql)

#df = pandas.read_sql_query(sql, conn)

#df.to_csv('TEST.csv')

#print('CSV sheet is ready to go!')

rows = cur.fetchall()

obs_list = []

for row in rows:

    d = collections.OrderedDict()
    d['addressee'] = row.NAME
    d['street'] = row.ADDRESS
    d['city'] = row.CITY
    d['state'] = row.STATE
    d['zipcode'] = row.ZIP
    obs_list.append(d)

obs_file = 'TEST.json'
with open(obs_file, 'w') as file:
    json.dump(obs_list, file)


print('Run through API')


url = 'https://api.smartystreets.com/street-address?'

headers = {'content-type': 'application/json'}

with open('test1.json', 'r') as run:

    dict_run = run.readlines()

    dict_ready = (''.join(dict_run))

r = requests.post(url , data=dict_ready, headers=headers)

ss_output = r.text

output = 'output.json'

with open(output,'w') as of:

    json.dump(ss_output, of)

print('I think it works')

f = open('output.json')

   data = json.load(f)

data_1 = data['analysis']

data_2 = data['metadata']

data_3 = data['components']

entity_data = open('TEST.csv','w')

csvwriter = csv.writer(entity_data)

count = 0

count2 = 0

count3 = 0

for ent in data_1:

    if count == 0:

        header = ent.keys()

        csvwriter.writerow(header)

        count += 1

    csvwriter.writerow(ent.values())

for ent_2 in data_2:

    if count2 == 0:

        header2 = ent_2.keys()

        csvwriter.writerow(header2)

        count2 += 1

    csvwriter.writerow(ent_2.values())

for ent_3 in data_3:

    if count3 == 0:

        header3 = ent_3.keys()

        csvwriter.writerow(header3)

        count3 += 1

    csvwriter.writerow(ent_3.values())

entity_data.close()

API的示例输出:

[
    {
        "input_index": 0,
        "candidate_index": 0,
        "delivery_line_1": "1 Santa Claus Ln",
        "last_line": "North Pole AK 99705-9901",
        "delivery_point_barcode": "997059901010",
        "components": {
            "primary_number": "1",
            "street_name": "Santa Claus",
            "street_suffix": "Ln",
            "city_name": "North Pole",
            "state_abbreviation": "AK",
            "zipcode": "99705",
            "plus4_code": "9901",
            "delivery_point": "01",
            "delivery_point_check_digit": "0"
        },
        "metadata": {
            "record_type": "S",
            "zip_type": "Standard",
            "county_fips": "02090",
            "county_name": "Fairbanks North Star",
            "carrier_route": "C004",
            "congressional_district": "AL",
            "rdi": "Commercial",
            "elot_sequence": "0001",
            "elot_sort": "A",
            "latitude": 64.75233,
            "longitude": -147.35297,
            "precision": "Zip8",
            "time_zone": "Alaska",
            "utc_offset": -9,
            "dst": true
        },
        "analysis": {
            "dpv_match_code": "Y",
            "dpv_footnotes": "AABB",
            "dpv_cmra": "N",
            "dpv_vacant": "N",
            "active": "Y",
            "footnotes": "L#"
        }
    },

    {
        "input_index": 1,
        "candidate_index": 0,
        "delivery_line_1": "Loop land 1",
        "last_line": "North Pole AK 99705-9901",
        "delivery_point_barcode": "997059901010",
        "components": {
            "primary_number": "1",
            "street_name": "Lala land",
            "street_suffix": "Ln",
            "city_name": "North Pole",
            "state_abbreviation": "AK",
            "zipcode": "99705",
            "plus4_code": "9901",
            "delivery_point": "01",
            "delivery_point_check_digit": "0"
        },
        "metadata": {
            "record_type": "S",
            "zip_type": "Standard",
            "county_fips": "02090",
            "county_name": "Fairbanks North Star",
            "carrier_route": "C004",
            "congressional_district": "AL",
            "rdi": "Commercial",
            "elot_sequence": "0001",
            "elot_sort": "A",
            "latitude": 64.75233,
            "longitude": -147.35297,
            "precision": "Zip8",
            "time_zone": "Alaska",
            "utc_offset": -9,
            "dst": true
        },
        "analysis": {
            "dpv_match_code": "Y",
            "dpv_footnotes": "AABB",
            "dpv_cmra": "N",
            "dpv_vacant": "N",
            "active": "Y",
            "footnotes": "L#"
        }
]

存储API输出后,问题是尝试将返回的输出(Sample output)解析为CSV格式。代码我试图这样做:

f = open('output.json')

data = json.load(f)

data_1 = data['analysis']

data_2 = data['metadata']

data_3 = data['components']

entity_data = open('TEST.csv','w')

csvwriter = csv.writer(entity_data)

count = 0

count2 = 0

count3 = 0

for ent in data_1:

    if count == 0:

        header = ent.keys()

        csvwriter.writerow(header)

        count += 1

    csvwriter.writerow(ent.values())

for ent_2 in data_2:

    if count2 == 0:

        header2 = ent_2.keys()

        csvwriter.writerow(header2)

        count2 += 1

    csvwriter.writerow(ent_2.values())

for ent_3 in data_3:

    if count3 == 0:

        header3 = ent_3.keys()

        csvwriter.writerow(header3)

        count3 += 1

    csvwriter.writerow(ent_3.values())

entity_data.close()

返回以下错误:TypeError:字符串索引必须是整数。正如有人善意地评论并指出,我似乎在迭代键而不是不同的词典,这就是我被卡住的地方,因为我不确定该怎么做?根据我的理解,看起来JSON被分成3个不同的数组,每个数组都有JSON对象,但根据结构,情况似乎并非如此?我为代码的长度道歉,但我想要与我想要实现的内容有一些相似之处。

2 个答案:

答案 0 :(得分:1)

考虑使用pandas的json_normalize()方法将嵌套项目展平为表格式df结构:

import pandas as pd
from pandas.io.json import json_normalize
import json

with open('Output.json') as f:
    data = json.load(f)

df = json_normalize(data)

df.to_csv('Output.csv')

请注意组件元数据分析会成为相应值的以句点分隔的前缀。如果不需要,请考虑重命名列。

JSON to CSV Output

答案 1 :(得分:0)

您正在使用json保存请求result.textresult.text是一个字符串,因此在通过json重新读取它时,您将获得相同的一个长字符串而不是list。尝试按原样编写result.text

output = 'output.json'
with open(output,'w') as of:
    of.write(ss_output)

这就是你提到TypeError:string indices must be integers的原因。 其余代码有多个问题。

  1. json中的数据是一个dicts列表,所以要得到data_1你需要列表理解,如下所示: data_1 = [x['analysis'] for x in data]

  2. 您可以将三种类型的行写入同一个csv文件:components,metadata和analyzis。那太奇怪了。

  3. 可能你必须重写代码的后半部分:每个数据类型打开三个csv_writers,然后迭代data个项目并将它们的字段写入相应的csv_writer。