Python 강좌 / JSON 데이터를 Python 객체로 변환하고 저장하기
JSON은 객체·배열·문자열·숫자 같은 구조화 데이터를 교환하는 텍스트 형식입니다. json 모듈의 load·dump는 파일을, loads·dumps는 문자열을 다루며 Python 객체 전체를 그대로 보존하는 형식은 아닙니다.
JSON과 Python 자료형의 대응
| JSON | Python |
|---|---|
| object | dict |
| array | list |
| string | str |
| true / false / null | True / False / None |
JSON 문자열과 키는 큰따옴표를 사용합니다. Python 코드처럼 작은따옴표나 주석을 임의로 넣으면 파싱이 실패합니다. 튜플은 저장 후 리스트가 될 수 있고 날짜·Decimal 같은 객체는 기본 설정으로 바로 저장되지 않습니다.
관련 동작과 지원 조건은 JSON 데이터를 Python 객체로 변환하고 저장하기 관련 공식 문서에서 확인할 수 있습니다.
전체 예제와 실행 결과
별도의 실습 폴더에서 아래 파일을 UTF-8로 저장합니다. 가상환경을 선택한 터미널에서 python json_demo.py 명령으로 실행합니다. macOS·Ubuntu에서 가상환경을 사용하지 않는 경우 명령 이름을 python3으로 바꿉니다.
json_demo.py 파일의 전체 내용입니다.
import json
from pathlib import Path
data = {"currency": "KRW", "expenses": [{"name": "점심", "amount": 8000}]}
path = Path("expenses-demo.json")
path.write_text(json.dumps(data, ensure_ascii=False, indent=2, allow_nan=False), encoding="utf-8")
loaded = json.loads(path.read_text(encoding="utf-8"))
amount = loaded["expenses"][0]["amount"]
if type(amount) is not int or amount < 0:
raise ValueError("invalid amount")
print(loaded["expenses"][0]["name"])
print(amount)
예상 결과는 다음과 같습니다.
점심 8000
파싱 성공과 데이터 유효성은 다릅니다
JSON으로 읽혔다고 업무 규칙까지 맞는 것은 아닙니다. 필수 키, 배열 여부, 각 항목의 형식과 범위를 검증해야 합니다. 예제는 bool을 정수로 인정하지 않으려고 type(amount) is int를 사용합니다. 일반적인 클래스 확장 허용 여부에 따라 isinstance가 적절한 경우도 있으므로 목적을 구분합니다.
Python json은 기본 설정에서 NaN·Infinity 같은 비표준 숫자를 허용하는 동작이 있습니다. 예제의 allow_nan=False는 저장 시 이런 값을 거부합니다. 엄격한 외부 입력을 읽을 때도 비표준 상수와 중복 키에 대한 정책을 별도로 검토합니다.
한글 표시와 파일 오류 확인
ensure_ascii=False는 한글을 이스케이프 문자열 대신 문자로 표현합니다. 파일 인코딩을 정하는 옵션과는 다르므로 파일에는 UTF-8을 별도로 지정합니다. indent는 보기 좋게 들여쓰는 옵션이며 데이터 의미를 바꾸지 않습니다.
잘못된 JSON에는 JSONDecodeError가 발생합니다. 끝의 쉼표나 따옴표를 고쳐야 하며 eval로 읽는 방식으로 바꾸면 안 됩니다. amount를 -1과 true로 각각 바꾸어 업무 검증이 거부하는지 확인하고 원래 값으로 되돌립니다.




