본문 바로가기

파일 형식 백과사전

중첩된 JSON을 엑셀에서 열리는 CSV로, 배열까지 한 줄씩 펼쳐 변환하기

API에서 받아 온 JSON을 엑셀로 열어 보려고 CSV로 바꿨더니,

한 칸 안에 {'name': '김민수', 'grade': 'gold'} 같은 덩어리가

통째로 들어가 버린 적이 있습니다. 표로 정리하려던 데이터가 오히려 더 읽기 어려워집니다.

 

원인은 JSON이 값 안에 또 다른 값을 품는 중첩 구조를 갖는 반면,

CSV는 행과 열이 반듯한 평평한 표만 담을 수 있다는 데 있습니다.

그래서 변환하려면 중첩을 먼저 펼쳐 줘야 합니다.

실제 데이터로 단계별로 해 보겠습니다.

다룰 데이터부터 보겠습니다

주문 정보를 담은 JSON입니다.

고객 정보는 객체 안에 들어 있고(customer),

주문 항목은 여러 개라 배열로 묶여 있습니다(items).

 

실무에서 흔히 만나는 모양입니다.

[
  {
    "order_id": 1001,
    "customer": { "name": "김민수", "grade": "gold" },
    "amount": 53000,
    "items": [
      { "product": "키보드", "qty": 1 },
      { "product": "마우스", "qty": 2 }
    ]
  }
]

 

그냥 CSV로 저장하면 왜 깨질까

이 상태로 바로 CSV로 저장하면, 중첩된 부분이 아래처럼 파이썬 표기 그대로 한 칸에 눌려 들어갑니다.

order_id,customer,amount,items
1001,"{'name': '김민수', 'grade': 'gold'}",53000,"[{'product': '키보드', 'qty': 1}, ...]"

customer 열과 items 열이 표가 아니라 글자 덩어리가 됐습니다. 엑셀로 열어도 필터나 정렬을 걸 수 없어 쓸모가 떨어집니다. 중첩을 먼저 풀어야 하는 이유입니다.


1단계: 객체를 열로 펼치기

파이썬 pandas에는 중첩 JSON을 펼치는 json_normalize가 있습니다. 먼저 이것만 쓰면 customer 안의 값이 customer.name, customer.grade라는 별도 열로 분리됩니다.

import pandas as pd

df = pd.json_normalize(data)
print(list(df.columns))
# ['order_id', 'amount', 'items', 'customer.name', 'customer.grade']

객체는 깔끔하게 열로 풀렸습니다. 다만 items는 여전히 배열이라 한 칸에 목록째 남아 있습니다. 배열은 한 단계가 더 필요합니다.

 

2단계: 배열을 한 줄씩 펼치기

주문 하나에 상품이 두 개면, 상품마다 한 줄로 나눠야 표가 됩니다.

record_path로 펼칠 배열을 지정하고, 바깥의 공통 값은 meta로 함께 붙입니다.

 

df = pd.json_normalize(
    data,
    record_path="items",                       # 이 배열을 줄 단위로 펼침
    meta=["order_id", ["customer", "name"], "amount"],  # 함께 붙일 바깥 값
)
df.to_csv("orders.csv", index=False, encoding="utf-8-sig")

실제로 저장된 CSV는 이렇게 나옵니다.

상품 세 개가 각각 한 줄이 되고, order_id와 customer.name 같은 바깥 값은 줄마다 반복됐습니다.

 

product,qty,order_id,customer.name,amount
키보드,1,1001,김민수,53000
마우스,2,1001,김민수,53000
USB 케이블,3,1002,이서연,12000

 

배열 항목 하나가 표의 한 줄이 되고, 바깥 정보는 각 줄에 채워집니다. 이제 엑셀에서 열면 필터도 정렬도 자연스럽게 걸립니다.


한글이 깨지지 않게 저장하는 포인트

위 코드에서 encoding="utf-8-sig"가 중요합니다.

엑셀은 그냥 UTF-8로 저장한 CSV의 한글을 깨뜨려 보여 주는 경우가 많은데,

BOM이라는 표시를 앞에 붙여 주는 utf-8-sig로 저장하면 엑셀이 한글을 바르게 인식합니다.

 

 

자주 묻는 질문

Q. 코드 없이 변환할 방법은 없나요?
간단한 구조라면 온라인 JSON to CSV 변환기도 있지만, 배열이 섞인 중첩은 도구마다 펼치는 방식이 달라 결과가 제각각입니다. 어떤 배열을 줄로 펼칠지 직접 정하려면 위처럼 코드로 다루는 편이 정확합니다.

 

Q. 배열이 여러 개면 어떻게 하나요?
record_path는 한 번에 배열 하나를 펼칩니다. 배열이 둘 이상이면 각각 따로 펼쳐 여러 CSV로 나누거나, 어떤 배열을 기준 줄로 삼을지 먼저 정해야 합니다.

 

Q. 바깥 값이 줄마다 반복되는 게 낭비 아닌가요?
표(CSV) 형식에서는 자연스러운 모습입니다. 반복이 부담되면 그 데이터는 CSV보다 관계형 구조나 원래 JSON으로 두는 편이 맞습니다.

 

중첩 JSON을 CSV로 옮길 때는 객체를 열로, 배열을 줄로 펼친다는 두 가지만 기억하면 됩니다.

지금 다루는 JSON에서 어느 부분이 객체이고 어느 부분이 배열인지부터 짚어 보면 변환 방향이 금세 잡힙니다.

 

 

받은 JSON을 엑셀로 봐야 할 때, XLSX로 변환하는 가장 깔끔한 방법

API에서 내려받은 데이터나 동료가 보내 준 파일이 .json인데, 정작 검토는 엑셀로 해야 하는 상황이 자주 생깁니다. 메모장으로 열면 중괄호와 따옴표가 빽빽해서 어디가 한 행인지조차 가늠이

richyeon.com

 

 

JSON "Expecting property name", "Expecting ',' delimiter" 오류, 증상별로 원인 찾고 고치기

JSON 파일을 읽히려는데 빨간 글씨로 이런 메시지가 뜬 적이 있을 것입니다.Expecting property name enclosed in double quotes: line 1 column 2 (char 1)Expecting ',' delimiter: line 1 column 15 (char 14)Illegal trailing comma before e

richyeon.com