2017-08-10 3 views
0

初めて投稿する! JSONデータ(辞書)をサーバーからCSVファイルに変換しています。取得されるキーと値は、配列である「宇宙飛行士」のネストから離れても問題ありません。基本的にすべてのJSON文字列は、0から独立した値として抽出したい宇宙飛行士の無制限の数を含むデータです。ネスト内のJSONネスト配列からキーと値を取得する

  • Astronaut1_Spaceships_First:Katabom
  • Astronaut1_Spaceships_Second:クラーケン
  • Astronaut1_name:Jebeddia
  • (...)
  • Astronaut2_gender:このような場合のために何か

うまくいけば、女性とそうです。ここでの問題は、ネストが辞書ではなく配列として設定されているため、何をすべきかわからないことです。私はdpathライブラリを試みただけでなく、巣をフラットにするが、何も変わっていない。何か案は?

import json 
import os 
import csv 
import datetime 
import dpath.util #Dpath library needs to be installed first 

datum = {"Mission": "Make Earth Greater Again", "Objective": "Prove Earth is flat", "Astronauts": [{"Spaceships": {"First": "Katabom", "Second": "The Kraken"}, "Name": "Jebeddiah", "Gender": "Hopefully male", "Age": 35, "Prefered colleages": [], "Following missions": [{"Payment_status": "TO BE CONFIRMED"}]}, {"Spaceships": {"First": "The Kraken", "Second": "Minnus I"}, "Name": "Bob", "Gender": "Hopefully female", "Age": 23, "Prefered colleages": [], "Following missions": [{"Payment_status": "TO BE CONFIRMED"}]}]} 

#Parsing process 
     parsed = json.loads(datum) #datum is the JSON string retrieved from the server 

def flattenjson(parsed, delim): 
    val = {} 
    for i in parsed.keys(): 
     if isinstance(parsed[i], dict): 
      get = flattenjson(parsed[i], delim) 
      for j in get.keys(): 
       val[i + delim + j] = get[j] 
     else: 
     val[i] = parsed[i] 

    return val 
flattened = flattenjson(parsed,"__") 

#process of creating csv file 
keys=['Astronaut1_Spaceship_First','Astronaut2_Spaceship_Second', 'Astronaut1_Name] #reduced to 3 keys for this example 

writer = csv.DictWriter(OD, keys ,restval='Null', delimiter=",", quotechar="\"", quoting=csv.QUOTE_ALL, dialect= "excel") 
     writer.writerow(flattened) 

#JSON DATA FROM SERVER 
{ 
"Mission": "Make Earth Greater Again", 
"Objective": "Prove Earth is flat", 
"Astronauts": [ { 
    "Spaceships": { 
    "First": "Katabom", 
    "Second": "The Kraken" 
    }, 
    "Name": "Jebeddiah", 
    "Gender": "Hopefully male", 
    "Age": 35, 
    "Prefered colleages": [], 
    "Following missions": [ 
    { 
     "Payment_status": "TO BE CONFIRMED" 
    } 
    ] 
}, 
{ 
    "Spaceships": { 
    "First": "The Kraken", 
    "Second": "Minnus I" 
    }, 
    "Name": "Bob", 
    "Gender": "Hopefully female", 
    "Age": 23, 
    "Prefered colleages": [], 
    "Following missions": [ 
    { 
     "Payment_status": "TO BE CONFIRMED" 
    } 
    ] 
}, 
    ] 
} 
] 

答えて

0

最初に、ここで定義したデータは、サーバーから抽出されるデータではありません。サーバーからのデータは文字列になります。このプログラムのデータはすでに処理されています。今度は、データを次のように仮定します。

datum = '{"Mission": "Make Earth Greater Again", "Objective": "Prove Earth is flat", "Astronauts": [{"Spaceships": {"First": "Katabom", "Second": "The Kraken"}, "Name": "Jebeddiah", "Gender": "Hopefully male", "Age": 35, "Prefered colleages": [], "Following missions": [{"Payment_status": "TO BE CONFIRMED"}]}, {"Spaceships": {"First": "The Kraken", "Second": "Minnus I"}, "Name": "Bob", "Gender": "Hopefully female", "Age": 23, "Prefered colleages": [], "Following missions": [{"Payment_status": "TO BE CONFIRMED"}]}]}' 

dpathライブラリは必要ありません。ここでの問題は、JSONフラットナーが埋め込みリストを処理しないことです。私が下に置いたものを使ってみてください。

import json 
def flattenjson(data, delim, topname=''): 
    """JSON flattener that can handle embedded lists and dictionaries""" 
    flattened = {} 
    def internalflat(int_data, name=topname): 
     if type(int_data) is dict: 
      for key in int_data: 
       internalflat(int_data[key], name + key + delim) 
     elif type(int_data) is list: 
      i = 1 
      for elem in int_data: 
       internalflat(elem, name + str(i) + delim) 
       i += 1 
     else: 
      flattened[name[:-len(delim)]] = int_data 
    internalflat(data) 
    return flattened 
#If you don't want mission or objective in csv file 
flattened_astronauts = flattenjson(json.loads(datum)["Astronauts"], "__", "Astronaut") 
keys = flattened_astronauts.keys().sort() 
writer = csv.DictWriter(OD, keys ,restval='Null', delimiter=",", quotechar="\"", quoting=csv.QUOTE_ALL, dialect= "excel") 
writer.writerow(flattened_astronauts) 
+0

、あなたは1行のcsvファイルをしたいと仮定すると、数回の試行の後、私は同じエラーを取得: flattened_astronauts = flattenjson({json.loads(データム)[ "宇宙飛行士"]}) はTypeError:非ハッシュをタイプ: 'リスト' 基本的に「宇宙飛行士」は辞書としてコード化されておらず、その機能では変更されません...... – Saphiron

+0

私の悪いです。あなたの要求に一層合うように関数を編集し、中括弧を削除しました(これは必須ではありませんでした。出力はすでに辞書です)。 –

+0

Works!どうもありがとうございます! 今問題は、宇宙飛行士の数がデータムに依存していることです。したがって、ヘッダは番号の変更(function:writer.writeheader())が行われるたびに生成されます。修正ヘッダーを設定する方法はありますか(データの宇宙飛行士の最大数は25です)、これにしたがってcsvファイルを書きますか? – Saphiron

関連する問題