2014-04-14 3 views
1

중첩 된 JSON 오브젝트 파일을 CSV로 변환하려고합니다. I 여기 이 컬럼이다 같은 JSON 샘플JSON에서 CSV 로의 파이썬 변환 문제

{ 
    "total_hosts" : [ 
     { 
     "TYPE" : "AGENT", 
     "COUNT" : 6 
     } 
    ], 
    "installed" : [ 
     { 
     "ID" : "admin-4.0", 
     "VERSION" : 4, 
     "ADDON_NAME" : "Administration" 
     }, 
     { 
     "ID" : "admin-2.0", 
     "VERSION" : 2, 
     "ADDON_NAME" : "Administration" 
     }, 
     { 
     "ID" : "ch-5.0", 
     "VERSION" : "5", 
     "ADDON_NAME" : "Control Host" 
     } 
    ], 
    "virtual_machine" : [ 
     { 
     "COUNT" : 4, 
     "TYPE" : "VM" 
     } 

TYPE, COUNT, ID, 버전이지만 값을 일부 이러한 값 1 개체가 또는 몇몇 개이므로이 가지는 문제는 각 객체가 아닌 행에 쓰기, 그래서 그 열에 대한 값이없는 경우 빈 공간을 작성하려고합니다.

코드는, 내가 Index out of range 오류가 발생하고 CSV

json_input = open('all.json') 
try: 
    decoded = json.load(json_input) 
# tell computer where to put CSV 
    outfile_path='Path to CSV' 
# open it up, the w means we will write to it 
    writer = csv.writer(open(outfile_path,'w')) 


     for index in range(len(decoded['installed'])): 
      row = [] 

      if decoded['total_hosts'][index]['TYPE'] is None: 
       row.append(str('')) 
      else: 
       row.append(str(decoded['total_hosts'][index]['TYPE'])) 
      if decoded['total_hosts'][index]['COUNT'] is None: 
       row.append(str('')) 
      else: 
       row.append(str(decoded['total_hosts'][index]['COUNT'])) 

      writer.writerow(row) 

로 쓰기 난 if에 대한 True/False 상태를 시도했다.

아무도 도와 줄 수 있습니까?

업데이트 : 예상 출력 : 해당 열의 값이 없을 때

TYPE,COUNT,ID,VERSION,ADDON_NAME,COUNT,TYPE 
AGENT,6,admin-4.0,4,Administration,4,VM 
, ,admin-2.0,2,Administration, , 
, ,cd-5.0,5,Control Host, , 

그래서 기본적으로 난 빈 공간이 필요합니다.

으론 수정 : OUTPUT :

AGENT,6,,, 
, ,admin-4.0,4,Administration 
, ,admin-2.0,2,Administration 
, ,ch-5.0,5,Control Host 

예상 출력 : 업데이트

AGENT,6,admin-4.0,4,Administration 
, ,admin-2.0,2,Administration 
, ,ch-5.0,5,Control Host 

: 나는 심지어 아직 위와 같은 결과를 얻었다

  row.append(str(entry.get('TYPE', ''))) 
      row.append(str(entry.get('COUNT', ''))) 
      row.append(str(entry.get('ID', ''))) 
      row.append(str(entry.get('VERSION', ''))) 
      row.append(str(entry.get('ADDON_NAME', ''))) 
      writer.writerow(row) 

을 시도했다. :(

+0

귀하의'installed'을하고 : 당신이 installed 후 항상 긴, 그리고 가정해야 할 것 파이썬 버전

(어떤이 itertools.izip_longest 추가) 2.6 전에 사용 같은 * 길이 *; 당신은'range (len (디코딩 된 [ 'installed']))')를 반복하고 있지만,'decoded [ 'total_hosts']'와'decoded [ '_ hosts']'리스트의 인덱스를 사용합니다 (후자는 아마도 오타입니다). –

+0

입력 및 예상 출력의 전체 예제를 포함해야합니다. – njzk2

+0

네 그것은 오타되었습니다 :) 실제로 파일의 모든 요소에 대해 루프를 반복하고 싶습니다. 그러나 그것들은 개별 객체/배열이므로 최대 개수의 요소가있는 배열을 가져 와서 반복합니다. 그래서 IF 조건을 넣습니다. 값이 없으면 공백을 추가해야합니다. 그래서 열 구조를 유지할 수 있습니다. – user3520135

답변

2

여기에 두 가지 실수가 있습니다. 당신은 decoded['total_hosts']이 많은이 없기 때문에 당신이 다음 decoded['total_hosts'] 목록을 사용하여 인덱스가이 인덱스 오류가 발생합니다 생성 decoded['installed']의 길이를 사용

  1. 은 항목

  2. KeyError 발생합니다 존재하지 않는 키에 액세스;.. 값이나 기본값을 검색하는 대신 dict.get() method를 사용을

그것은 필요가 인덱스를 생성하지 않으려면 목록을 통해 단지 루프 직접 훨씬 간단 :

for key in ('total_hosts', 'installed', 'virtual_machine'): 
    for entry in decoded[key]: 
     row = [entry.get('TYPE', ''), entry.get('COUNT', '')] 
     writer.writerow(row) 

경우 :

for host in decoded['total_hosts']: 
    row = [host.get('TYPE', ''), host.get('COUNT', '')] 
    writer.writerow(row) 

당신이 하나 이상의 키를 처리하기 위해 확장 할 수 있습니다 당신은 이 합쳐져서의 두 엔트리 출력을 합친 다음, itertools.izip_longest()을 사용하여리스트를 짝을 짓고, 더 짧은리스트가 부족할 때의 기본값을 사용하십시오 :

from itertools import izip_longest 

for t, i, v in izip_longest(decoded['total_hosts'], decoded['installed'], decoded['version'], fillvalue={}): 
    row = [t.get('TYPE', ''), t.get('COUNT', ''), 
      i('ID', ''), i('VERSION', ''), i.get('ADDON_NAME', ''), 
      v.get('COUNT', ''), v.get('TYPE', '')] 
    writer.writerow(row) 

이렇게하면 세 목록 중 하나가 다른 목록보다 짧아집니다.total_hosts` 목록이없는`

for i, installed in decoded['installed']: 
    t = decoded['types'][i] if i < len(decoded['types']) else {} 
    v = decoded['version'][i] if i < len(decoded['version']) else {} 
    row = [t.get('TYPE', ''), t.get('COUNT', ''), 
      installed['ID'], installed['VERSION'], installed['ADDON_NAME'], 
      v.get('COUNT', ''), v.get('TYPE', '')] 
    writer.writerow(row) 
+0

질문이 업데이트되었습니다. – user3520135

+0

@ user3520135 :이 오류는 대개 앞 줄에')'또는']'를 닫음을 잊었음을 나타냅니다. –

+0

@ user3520135 :'row = []'줄은 완전히 중복되어 있습니다. –