pandas.read_json 은 JSON 문자열 또는 파일을 DataFrame 으로 변환. orient 파라미터가 핵심, JSON 의 구조가 어떤 형태인지를 선언한다.
반대 방향은 DataFrame.to_json : DataFrame 을 JSON 으로 직렬화.
사용 상황
상황
권장
REST API 응답 (배열 of 객체)
orient='records'
pandas 자체 직렬화 / 복원
orient='split'
줄당 객체 (JSONL, 로그)
lines=True
대용량 JSONL 스트리밍
lines=True, chunksize=N
중첩 JSON 평탄화
pd.json_normalize()
orient 옵션 한눈에 보기
orient
JSON 구조
설명
records
[{col: val, ...}, ...]
배열 of 객체, API 응답
columns
{col: {idx: val}}
기본값, 열 중심
index
{idx: {col: val}}
행 중심
split
{columns:[...], index:[...], data:[ [...] ]}
효율적, 메타 보존
table
JSON Table Schema 포함
dtype 메타데이터 포함
values
[[v1, v2], ...]
헤더 없는 raw 2D
flowchart LR
A["JSON 입력"] --> B{"orient 선택"}
B -->|"records"| C["배열 of 객체"]
B -->|"split"| D["효율적 직렬화"]
B -->|"table"| E["dtype 메타 포함"]
B -->|"values"| F["헤더 없는 raw"]
C --> G["DataFrame"]
D --> G
E --> G
F --> G
records: 가장 흔한 패턴
python
import pandas as pdimport iojson_text = '[{"name":"Alice","age":30},{"name":"Bob","age":25}]'df = pd.read_json(io.StringIO(json_text), orient='records')print(df)print(df.dtypes)
결과
name age0 Alice 301 Bob 25name objectage int64dtype: object
# ISO 8601 문자열 자동 파싱 시도df = pd.read_json(path, orient='records', convert_dates=['created_at'])# epoch ms → datetimedf = pd.read_json(path, convert_dates=True) # 모든 숫자형 날짜 시도# 날짜 파싱 비활성화df = pd.read_json(path, convert_dates=False)
API 응답 처리
import requestsresponse = requests.get('https://api.example.com/users')data = response.json()# 방법 1: pd.read_json (문자열 경로)import io, jsondf = pd.read_json(io.StringIO(json.dumps(data)), orient='records')# 방법 2: pd.DataFrame (더 명확, data 가 list of dict 이면)df = pd.DataFrame(data)
to_json (저장)
# records 형태 (가장 일반적)df.to_json('out.json', orient='records', force_ascii=False, indent=2)# JSONL (한 줄 한 객체)df.to_json('out.jsonl', orient='records', lines=True, force_ascii=False)# 날짜 ISO 포맷df.to_json('out.json', orient='records', date_format='iso', force_ascii=False)# 문자열로 반환 (파일 아닌 메모리)json_str = df.to_json(orient='records', force_ascii=False)
orient 별 to_json / read_json 왕복
for orient in ['records', 'split', 'index', 'columns', 'table']: buf = df.to_json(orient=orient) df2 = pd.read_json(buf, orient=orient) assert df.equals(df2), f'{orient} 왕복 실패'
table orient 는 dtype 까지 보존하므로 가장 완전한 직렬화.
함정
1. orient 기본값이 columns
pd.read_json('[{"a":1,"b":2}]')# orient='columns' 기본 → 예상과 다른 결과pd.read_json('[{"a":1,"b":2}]', orient='records') # ✓ 명시
API 응답을 처리할 때 orient='records' 를 명시하지 않으면 컬럼이 뒤집힌 구조가 나온다.
2. 한글이 \u escape 로 저장
df.to_json('out.json') # 한글이 \uXXXX 로df.to_json('out.json', force_ascii=False) # ✓ 한글 그대로
3. 날짜가 epoch ms (숫자) 로 저장
df.to_json('out.json') # datetime → 정수 (ms)df.to_json('out.json', date_format='iso') # ✓ "2024-01-15T00:00:00"
4. 대용량 단일 파일 메모리 폭주
# ❌ 한 번에 로드df = pd.read_json('10GB.jsonl', lines=True)# ✓ 청크로for chunk in pd.read_json('10GB.jsonl', lines=True, chunksize=100_000): process(chunk)
5. read_json 과 pd.DataFrame 차이
pd.read_json(path) : 파일/URL/문자열에서 직접 읽기, orient 파싱 포함
pd.DataFrame(list_of_dict) : 이미 파싱된 파이썬 객체에서 생성, 더 명확
API 응답처럼 이미 파이썬 객체로 파싱된 경우 pd.DataFrame(data) 가 더 직관적.
6. index orient 와 columns orient 혼동
# columns (기본): {컬럼명: {인덱스: 값}}# index: {인덱스: {컬럼명: 값}}# 둘 다 dict of dict 이지만 키 순서가 반대
💬 댓글