2012-09-06 92 views
1

我首先說我是python的新手。我編寫了一個將.json文件轉換爲csv格式的腳本。我設法編寫了一個腳本來完成這項工作,但是如果json文件的格式發生改變,我認爲我的腳本不會工作。我的腳本假設json文件在任何時候都是相同的格式。Python的JSON到CSV轉換腳本?

<json file example> 
{ 
"Order": 
    { 
     "order_id":"8251662", 
     "order_date":"2012-08-20 13:17:37", 
     "order_date_shipped":"0000-00-00 00:00:00", 
     "order_status":"fraudreview", 
     "order_ship_firstname":"pam", 
     "order_ship_lastname":"Gregorio", 
     "order_ship_address1":"1533 E. Dexter St", 
     "order_ship_address2":"", 
     "order_ship_city":"Covina", 
     "order_ship_state":"CA", 
     "order_ship_zip":"91746", 
     "order_ship_country":"US United States", 
     "order_ship_phone":"6268936923", 
     "order_ship_email":"[email protected]", 
     "order_bill_firstname":"pam", 
     "order_bill_lastname":"Gregorio", 
     "order_bill_address1":"1533 E. Dexter St", 
     "order_bill_address2":"", 
     "order_bill_city":"Covina", 
     "order_bill_state":"CA", 
     "order_bill_zip":"91746", 
     "order_bill_country":"US United States", 
     "order_bill_phone":"6268936923", 
     "order_bill_email":"[email protected]", 
     "order_gift_message":"", 
     "order_giftwrap":"0", 
     "order_gift_charge":"0", 
     "order_shipping":"Standard (Within 5-10 Business Days)", 
     "order_tax_charge":"62.83", 
     "order_tax_shipping":"0", 
     "order_tax_rate":"0.0875", 
     "order_shipping_charge":"7.5", 
     "order_total":"788.33", 
     "order_item_count":"12", 
     "order_tracking":"", 
     "order_carrier":"1" 
    }, 

"Items": 
    [ 
    { 
     "item_id":"25379", 
     "item_date_shipped":"", 
     "item_code":"17345-J3553-J35532", 
     "item_quantity":"2","item_taxable":"YES", 
     "item_unit_price":"32","item_shipping":"0.67", 
     "item_addcharge_price":"0", 
     "item_description":" ABC Slide Bracelet: : Size: OS: Silver Sku: J35532", 
     "item_quantity_returned":"0", 
     "item_quantity_shipped":"0", 
     "item_quantity_canceled":"0", 
     "item_status":"pending", 
     "item_product_id":"17345", 
     "item_product_kit_id":"0", 
     "item_product_sku":"J35532", 
     "item_product_barcode":"881934310775", 
     "item_tracking":"", 
     "item_carrier":"0", 
     "item_source_orderid":"" 
    }, 
    { 
     "item_id":"25382", 
     "item_date_shipped":"", 
     "item_code":"17608-J3809-J3809C", 
     "item_quantity":"1", 
     "item_taxable":"YES", 
     "item_unit_price":"22", 
     "item_shipping":"0.23", 
     "item_addcharge_price":"0", 
     "item_description":" \"ABC Starter Bracelet 7 1\/4\"\"\": : Size: OS: Silver Sku: J3809C", 
     "item_quantity_returned":"0", 
     "item_quantity_shipped":"0", 
     "item_quantity_canceled":"0", 
     "item_status":"pending", 
     "item_product_id":"17608", 
     "item_product_kit_id":"0", 
     "item_product_sku":"J3809C", 
     "item_product_barcode":"881934594175", 
     "item_tracking":"", 
     "item_carrier":"0", 
     "item_source_orderid":"" 
    }, 
    { 
     "item_id":"25385", 
     "item_date_shipped":"", 
     "item_code":"17687-J9200-J92000", 
     "item_quantity":"2", 
     "item_taxable":"YES", 
     "item_unit_price":"12", 
     "item_shipping":"0.25", 
     "item_addcharge_price":"0", 
     "item_description":" ABC Cathedral Bead: : Size: OS: Silver Sku: J92000", 
     "item_quantity_returned":"0", 
     "item_quantity_shipped":"0", 
     "item_quantity_canceled":"0", 
     "item_status":"pending", 
     "item_product_id":"17687", 
     "item_product_kit_id":"0", 
     "item_product_sku":"J92000", 
     "item_product_barcode":"881934602832", 
     "item_tracking":"", 
     "item_carrier":"0", 
     "item_source_orderid":"" 
    }, 
    { 
     "item_id":"25388", 
     "item_date_shipped":"", 
     "item_code":"17766-J9240-J92402", 
     "item_quantity":"2", 
     "item_taxable":"YES", 
     "item_unit_price":"22", 
     "item_shipping":"0.46", 
     "item_addcharge_price":"0", 
     "item_description":" ABC Ice Diva Bead: : Size: OS: Silver Sku: J92402", 
     "item_quantity_returned":"0", 
     "item_quantity_shipped":"0", 
     "item_quantity_canceled":"0", 
     "item_status":"pending", 
     "item_product_id":"17766", 
     "item_product_kit_id":"0", 
     "item_product_sku":"J92402", 
     "item_product_barcode":"881934655838", 
     "item_tracking":"", 
     "item_carrier":"0", 
     "item_source_orderid":"" 
    }, 
    ], 

"FraudReasons": 
    [ 
    { 
     "order_id":"11957", 
     "fraud_reason":"order total exceeds max amount" 
    }, 
    { 
     "order_id":"11957", 
     "fraud_reason":"order exceeds max item count" 
    } 
] 
} 

我的劇本目前正常工作與此JSON文件,但如果只有一個項目或一個fraudreason它不會工作。這是我的腳本的代碼。

<script code> 
#!/usr/bin/python 
import simplejson as json 
import optparse 
import pycurl 
import sys 
import csv 

json_data = open(file) 
data = json.load(json_data) 
json_data.close() 

csv_file = '/tmp/' + str(options.orderId) + '.csv' 
orders = data['Order'] 
items = data['Items'] 
frauds = data['FraudReasons'] 

o = csv.writer(open(csv_file, 'w'), lineterminator=',') 

o.writerow([orders['order_id'],orders['order_date'],orders['order_date_shipped'],orders['order_status'],orders['order_ship_firstname'],orders['order_ship_lastname'],orders['order_ship_address1'],orders['order_ship_address2'],orders['order_ship_city'],orders['order_ship_state'],orders['order_ship_zip'],orders['order_ship_country'],orders['order_ship_phone'],orders['order_ship_email'],orders['order_bill_firstname'],orders['order_bill_lastname'],orders['order_bill_address1'],orders['order_bill_address2'],orders['order_bill_city'],orders['order_bill_state'],orders['order_bill_zip'],orders['order_bill_country'],orders['order_bill_phone'],orders['order_bill_email'],orders['order_gift_message'],orders['order_giftwrap'],orders['order_gift_charge'],orders['order_shipping'],orders['order_tax_charge'],orders['order_tax_shipping'],orders['order_tax_rate'],orders['order_shipping_charge'],orders['order_total'],orders['order_item_count'],orders['order_tracking'],orders['order_carrier']]) 

for item in items: 
    o.writerow([item['item_id'],item['item_date_shipped'],item['item_code'],item['item_quantity'],item['item_taxable'],item['item_unit_price'],item['item_shipping'],item['item_addcharge_price'],item['item_description'],item['item_quantity_returned'],item['item_quantity_shipped'],item['item_quantity_canceled'],item['item_status'],item['item_product_id'],item['item_product_kit_id'],item['item_product_sku'],item['item_product_barcode'],item['item_tracking'],item['item_carrier'],item['item_source_orderid']]) 

for fraud in frauds: 
    o.writerow([fraud['fraud_reason']],) 

我也一直無法弄清楚如何不使用我希望有人能幫助我在此提前

感謝標籤。

回答

2

您可能需要使用csv.DictWriter

# It's considered best to stash the main logic of your script 
    # in a main() function like this. 
    def main(filename, options): 
     with open(filename) as fi: 
      data = json.load(fi) 

     csv_file = '/tmp/' + str(options.orderId) + '.csv' 
     order = data['Order'] 
     items = data['Items'] 
     frauds = data['FraudReasons'] 

     # Here's one way to keep this maintainable if the JSON 
     # format changes, and you don't care too much about the 
     # order of the fields... 
     orders_fields = sorted(orders.keys()) 
     item_fields = sorted(items[0].keys()) if items else() 
     fraud_fields = sorted(fraud[0].keys()) if fraud else() 

     csv_options = dict(lineterminator=',') 

     with open(csv_file, 'w') as fo: 
      o = csv.DictWriter(fo, order_fields, **csv_options) 
      o.writeheader() 
      o.writerow(orders) 

      fo.write('\n') # Optional, if you want to keep them separated. 
      o = csv.DictWriter(fo, item_fields, **csv_options) 
      o.writeheader() 
      o.writerows(items) 

      fo.write('\n') # Optional, if you want to keep them separated. 
      o = csv.DictWriter(fo, fraud_fields, **csv_options) 
      o.writeheader() 
      o.writerows(frauds) 

    # If this script is run from the command line, just run 
    # main(). Here's the place to use `optparse`. 
    if __name__ == '__main__': 
     main(...) # You'll need to fill in the main() arguments... 

如果需要指定字段的順序,將它們分配到這樣一個元組:

orders_fields = (
    'order_id', 
    'order_date', 
    'order_date_shipped', 
    # ... etc. 
    ) 
+0

大衛 - 感謝您爲您的文章。它幫助了我很多。然而,如果我想按照它們在json文件中顯示的順序來保持字段的順序呢? –

+0

另一個問題我不熟悉這種類型的語法(主)和所有。你能告訴我如何從命令行運行它嗎?我很抱歉這樣簡單的問題(愚蠢)我是Python的新手我更熟悉Perl,但我想學習如何在python中編寫代碼。 –

+0

如果直接從命令行運行,則會執行'if __name__ =='__main __''塊。此設置的主要優點是您可以稍後將該模塊作爲另一個腳本的庫使用。以下是關於此問題的文章:http://effbot.org/pyfaq/tutor-what-is-if-name-main-for.htm –

0

你應該問生成的JSON-對象(data)爲字段的名稱。要保留輸入順序,告訴JSON使用collections.OrderedDict而不是純dict(需要Python 2.7):與csv.DictWriter

import json 
from collections import OrderedDict as ordereddict 

data = json.loads(open('mydata.json', object_pairs_hook=ordereddict) 
orders = data['Order'] 
print orders.keys() # Will print the keys in the order they were read 

然後可以使用orders.keys(),而不是你硬編碼的列表,無論是與writerow或(簡單) 。

注意,這裏使用了默認json,不simplejson,並且需要Python 2.7的ordered_pairs_hook參數和OrderedDict類型。

編輯:是的,我從評論中看到,你堅持使用2.4。您可以從PyPI中的ordereddict,並且可以擴展JSONDecoder類,並與cls參數(見here)通過它,而不是object_pairs_hook,但這是醜陋和更多的工作...

+0

感謝alexis,我得到了使用上述建議的腳本。我希望我能升級到2.7,這樣我就可以利用這些很酷的東西。你知道我是否可以在我的版本中安裝2.7? –

+0

我相信你可以,但你必須弄清楚如何。 – alexis

+0

「我希望我可以升級到2.7」就像我曾經在RHEL上沒有訪問互聯網一樣。我的解決方案是使用來自http://www.activestate.com/activepython/downloads的python 2.7+用於我的平臺,將它安裝到某處並從那裏運行python解釋器(您可能希望先將安裝路徑放入PATH中env var) – dim