2016-07-19 32 views
0

50個のカラムを持つフラットCSVファイル(名前はファーストネーム、ラストネーム、アドレスなどとしましょう)は、タブ区切りですべてのフィールドを囲んでいます。いくつかのフィールドがネストされる必要がある場合、フラットCSVをJSONに変換します。

これをJSONファイルに変換する必要がありますが、いくつかのCSV列をネストされたフィールドに変換する必要があります。ネストされたフィールドには、列の行の値を除き、値(これは必須フィールドを持つAPI用です)。ネストされたフィールドになる必要がある列を事前に知っています。

FirstName LastName Address 
John   Doe   21 Python Street 

これで希望JSON出力:

{ 
    "FirstName": "John", 
    "LastName": "Doe", 
    "Shipping Details": [ 
    { 
    "Generic Field 1": "Generic Value 1", 
    "Generic Field 2": "Generic Value 2", 
    "Address": "21 Python Street" 
    } 
    ] 
} 

ので、簡単のため、のは、これはCSVファイルの最初の3列の最初の行の構造であるとしましょう

50列の完全なCSVでは、これらの余分な汎用値を使って、ネストされたフィールドを解析するのに必要な列がさらにいくつかあります。

これを行うにはどうすればよいですか?

+1

でください[あなたの質問を編集して、この出力につながる入力のサンプルを提供してください。 –

+1

「フラット」と言うとき、行がない、つまり1つの行を意味しますか?上級者の列名を知っていますか、それともヘッダーがありますか? –

+0

csvファイルの読み込みに問題はありませんか?そうでなければ、すべての行について:辞書を作成する(入れ子にされた値は辞書内の辞書でなければならない)。 'json.dump(Dict、outfile)'にするだけで、辞書で埋められた辞書をダンプできます。 – pwnsauce

答えて

3

DictReaderを使用し、Shipping Detailsを追加してAddressを削除して行を操作します。

j = [] 

with open("/tmp/so.csv") as f: 
    reader = csv.DictReader(f, delimiter="\t") 
    for row in reader: 
     # Add 'Shipping Details' to row. 
     # Note that something like this will have to be done 
     # for *every* column you want to change. 
     row["Shipping Details"] = { 
      "Generic Field 1": "Generic Value 1", 
      "Generic Field 2": "Generic Value 2", 
      "Address": row["Address"]} 

     # We don't need the 'Address' anymore. 
     del(row["Address"]) 

     # Collect the changed row in the list of rows. 
     j.append(row) 
print(json.dumps(j)) 

出力(糸くずの後):あなただけに持って、その後

def nested_key(row,key_to_swap, pre_filled_dict): 
    pre_filled_dict[key_to_swap]=row[key_to_swap] 
    row[key_to_swap]=pre_filled_dict[key_to_swap] 

[{ 
    "LastName": "Doe", 
    "Shipping Details": { 
     "Address": "21 Python Street", 
     "Generic Field 1": "Generic Value 1", 
     "Generic Field 2": "Generic Value 2" 
    }, 
    "FirstName": "John" 
}] 
+0

これは方法です。しかし、彼は '' Shipping Details "' csvにネストされた値がたくさんある場合、多くの時間をあなたがしたことをやらなければならないかもしれません。 – pwnsauce

+0

はい、そうです。ロジックをループ外に移動して関数にすることができます。しかし、私はそれを取り除く方法を見ない。 –

+0

@FullNameこれは、私が探していた出力を提供するものではありません。ネストされたフィールド(「Shipping Details」)は、辞書が内部にあるリストでなければならず、変換されたレコードはリスト例。 – neuron

1

が@FullNameの答えを継続するには、多分あなたは新しいキーcreats機能を持たせることができますpre_filled_dictを作成します。つまり、

pre_filled_adsress={ 
      "Generic Field 1": "Generic Value 1", 
      "Generic Field 2": "Generic Value 2"} 

とループのために:

for row in reader: 
    nested_key(row,"Address",pre_filled_address) 
    nested_key(row,"2nd_nested_key",second_dict) 

私はこれが必要になるかわからない、私はあなたが持っているどのように多くのものを価値の分かりません。

+0

ああ... 2つの値のためにこれを気にするべきではありません。 – pwnsauce

+1

'key_to_swap'を引用符で囲むべきではありません。 –

1

ネストされたdictsを持つ列を定義する辞書を作成し、その列の値を移入するために使用することができます。カスタマイズを単一の統合された場所に保つことで、読み込み/保守が容易になり、他のcsv形式への移植が容易になります。

import copy 

CSV_CONFIG = { 
    2: { 
     # Column 3 (zero-based index 2) 
     "name": "Shipping Details", 
     "Generic Field 1": "Generic Value 1", 
     "Generic Field 2": "Generic Value 2", 
     }, 
    3: { 
     # Column 4 (zero-based index 3) 
     "name": "Personage", 
     "Generic Field 3": "Generic Value 3", 
     "Generic Field 4": "Generic Value 4", 
     }, 
} 

今、あなたは異なっCSV_CONFIG複数のネストされた列を表示するために追加"personage"列でデータを考えると

data = [] 
with open(file, "r") as fh: 
    col_names = fh.readline().strip().split(",") 

    for line in fh.readlines(): 
     line_data = {} 
     cols = line.strip().split(",") 
     for i in range(len(cols)): 
      if i not in CSV_CONFIG: 
       #this is not a nested column 
       line_data[col_names[i]] = cols[i] 
      else: 
       #this column is nested 
       nested_dict = copy.deepcopy(CSV_CONFIG[i]) 
       nested_dict[col_names[i]] = cols[i] 
       del nested_dict["name"] 
       line_data[CSV_CONFIG[i]["name"]] = nested_dict 
     data.append(line_data) 

に何があるかに基づいてdataを投入、dataは今

[{ 
    'FirstName': 'John', 
    'LastName': 'Doe', 
    'Personage': { 
     'Generic Field 3': 'Generic Value 3', 
     'Generic Field 4': 'Generic Value 4', 
     'Vitality': 'Alive' 
    }, 
    'Shipping Details': { 
     'Address': '21 Pytohn Street', 
     'Generic Field 1': 'Generic Value 1', 
     'Generic Field 2': 'Generic Value 2' 
    } 
}, { 
    'FirstName': 'Elvis', 
    'LastName': 'Presley', 
    'Personage': { 
     'Generic Field 3': 'Generic Value 3', 
     'Generic Field 4': 'Generic Value 4', 
     'Vitality': 'Deceased' 
    }, 
    'Shipping Details': { 
     'Address': 'Elvis Presley Blvd', 
     'Generic Field 1': 'Generic Value 1', 
     'Generic Field 2': 'Generic Value 2' 
    } 
}] 
関連する問題