Python으로 JSON 다루기 - glasslego/getting-started-with-python GitHub Wiki
1. JSON이란?
1.1 JSON 개념
**JSON (JavaScript Object Notation)**은 데이터를 저장하고 전송하기 위한 경량의 텍스트 기반 데이터 교환 형식
주요 특징
- 경량성: XML보다 간결하고 읽기 쉬움
- 언어 독립적: JavaScript에서 시작되었지만 대부분의 프로그래밍 언어에서 지원
- 구조화: 키-값 쌍으로 구성된 구조화된 데이터
- 표준화: RFC 7159 표준으로 정의됨
사용 용도
- 웹 API: REST API의 데이터 전송 형식
- 설정 파일: 애플리케이션 설정 저장
- 데이터 저장: NoSQL 데이터베이스 (MongoDB 등)
- 데이터 교환: 시스템 간 데이터 전송
1.2 JSON 문법 규칙
기본 문법
{
"name": "Alice",
"age": 25,
"isStudent": false,
"address": null,
"hobbies": ["reading", "swimming", "coding"],
"contact": {
"email": "[email protected]",
"phone": "010-1234-5678"
}
}
데이터 타입
- 문자열: 쌍따옴표로 감싸기
"hello"
- 숫자: 정수나 소수
42
,3.14
- 불린:
true
또는false
- null:
null
- 객체: 중괄호
{}
로 감싸진 키-값 쌍 - 배열: 대괄호
[]
로 감싸진 값들의 목록
문법 규칙
- 키는 반드시 문자열이고 쌍따옴표로 감싸야 함
- 문자열은 쌍따옴표만 사용 (홑따옴표 불가)
- 마지막 요소 뒤에 쉼표 금지
- 주석 사용 불가
2. Python에서 JSON 다루기
2.1 json 모듈 기본 사용법
import json
# 1. Python 객체를 JSON 문자열로 변환 (직렬화/Serialization)
data = {
"name": "Alice",
"age": 25,
"is_student": False,
"grades": [85, 92, 78],
"address": {
"city": "Seoul",
"zipcode": "12345"
}
}
# dict를 JSON 문자열로 변환
json_string = json.dumps(data)
print("JSON 문자열:")
print(json_string)
print(f"타입: {type(json_string)}")
# 2. JSON 문자열을 Python 객체로 변환 (역직렬화/Deserialization)
json_text = '{"name": "Bob", "age": 30, "hobbies": ["music", "sports"]}'
python_obj = json.loads(json_text)
print("\nPython 객체:")
print(python_obj)
print(f"타입: {type(python_obj)}")
print(f"이름: {python_obj['name']}")
# 3. 들여쓰기로 보기 좋게 출력
pretty_json = json.dumps(data, indent=2)
print("\n들여쓰기 적용된 JSON:")
print(pretty_json)
# 4. 한글 문자 처리
korean_data = {
"이름": "김철수",
"나이": 30,
"직업": "개발자",
"취미": ["독서", "영화감상", "코딩"]
}
# ensure_ascii=False로 한글 문자 그대로 유지
korean_json = json.dumps(korean_data, ensure_ascii=False, indent=2)
print("\n한글 데이터 JSON:")
print(korean_json)
# 5. 키 정렬
sorted_json = json.dumps(data, indent=2, sort_keys=True)
print("\n키 정렬된 JSON:")
print(sorted_json)
2.2 JSON 파일 읽기와 쓰기
import json
# JSON 파일에 데이터 저장
students_data = {
"course": "Python Programming",
"semester": "2024-1",
"instructor": "김선생",
"students": [
{
"id": 1,
"name": "Alice",
"age": 22,
"grades": {"midterm": 85, "final": 92},
"active": True
},
{
"id": 2,
"name": "Bob",
"age": 23,
"grades": {"midterm": 78, "final": 88},
"active": True
},
{
"id": 3,
"name": "Charlie",
"age": 21,
"grades": {"midterm": 92, "final": 95},
"active": False
}
]
}
# 파일에 JSON 데이터 쓰기
with open('students.json', 'w', encoding='utf-8') as f:
json.dump(students_data, f, ensure_ascii=False, indent=2)
print("students.json 파일이 생성되었습니다.")
# 파일에서 JSON 데이터 읽기
with open('students.json', 'r', encoding='utf-8') as f:
loaded_data = json.load(f)
print("\n파일에서 읽어온 데이터:")
print(f"과목: {loaded_data['course']}")
print(f"학기: {loaded_data['semester']}")
print(f"강사: {loaded_data['instructor']}")
print(f"학생 수: {len(loaded_data['students'])}")
# 학생 정보 출력
print("\n학생 목록:")
for student in loaded_data['students']:
avg_grade = (student['grades']['midterm'] + student['grades']['final']) / 2
status = "재학" if student['active'] else "휴학"
print(f" {student['name']} (ID: {student['id']}): 평균 {avg_grade:.1f}점 - {status}")
# 특정 학생 정보 수정
for student in loaded_data['students']:
if student['name'] == 'Bob':
student['grades']['final'] = 95 # Bob의 기말고사 점수 수정
break
# 수정된 데이터를 다시 파일에 저장
with open('students_updated.json', 'w', encoding='utf-8') as f:
json.dump(loaded_data, f, ensure_ascii=False, indent=2)
print("\n수정된 데이터가 'students_updated.json'에 저장되었습니다.")
# 실용적인 예시: 설정 파일 관리
config_data = {
"database": {
"host": "localhost",
"port": 5432,
"name": "myapp_db",
"username": "admin"
},
"api": {
"timeout": 30,
"retries": 3,
"base_url": "https://api.example.com"
},
"features": {
"debug_mode": False,
"logging_enabled": True,
"cache_enabled": True
}
}
# 설정 파일 저장
with open('config.json', 'w', encoding='utf-8') as f:
json.dump(config_data, f, indent=2)
print("\n설정 파일 'config.json'이 생성되었습니다.")
# 설정 파일 읽기 및 사용
with open('config.json', 'r', encoding='utf-8') as f:
config = json.load(f)
# 설정값 사용 예시
db_host = config['database']['host']
db_port = config['database']['port']
api_timeout = config['api']['timeout']
debug_mode = config['features']['debug_mode']
print(f"\n현재 설정:")
print(f" 데이터베이스: {db_host}:{db_port}")
print(f" API 타임아웃: {api_timeout}초")
print(f" 디버그 모드: {'켜짐' if debug_mode else '꺼짐'}")
# JSON 파일에서 특정 데이터만 추출
def get_active_students(json_file):
"""재학 중인 학생들만 반환"""
with open(json_file, 'r', encoding='utf-8') as f:
data = json.load(f)
active_students = []
for student in data['students']:
if student['active']:
active_students.append({
'name': student['name'],
'id': student['id'],
'average': (student['grades']['midterm'] + student['grades']['final']) / 2
})
return active_students
# 활성 학생 목록 조회
active_students = get_active_students('students.json')
print(f"\n재학 중인 학생 ({len(active_students)}명):")
for student in active_students:
print(f" {student['name']} (ID: {student['id']}): 평균 {student['average']:.1f}점")
# 여러 JSON 파일 처리
json_files = ['students.json', 'config.json']
for filename in json_files:
try:
with open(filename, 'r', encoding='utf-8') as f:
data = json.load(f)
print(f"\n'{filename}' 파일 정보:")
print(f" 키 개수: {len(data)}")
print(f" 최상위 키들: {list(data.keys())}")
except FileNotFoundError:
print(f"'{filename}' 파일을 찾을 수 없습니다.")
except json.JSONDecodeError as e:
print(f"'{filename}' 파일의 JSON 형식이 올바르지 않습니다: {e}")
# 안전한 JSON 파일 처리 함수
def safe_load_json(filename, default=None):
"""안전하게 JSON 파일을 로드하는 함수"""
try:
with open(filename, 'r', encoding='utf-8') as f:
return json.load(f)
except FileNotFoundError:
print(f"파일 '{filename}'을 찾을 수 없습니다.")
return default
except json.JSONDecodeError as e:
print(f"JSON 파싱 오류: {e}")
return default
except Exception as e:
print(f"예상치 못한 오류: {e}")
return default
# 안전한 파일 로드 테스트
safe_data = safe_load_json('nonexistent.json', {})
print(f"\n존재하지 않는 파일 로드 결과: {safe_data}")
safe_students = safe_load_json('students.json', [])
print(f"안전하게 로드된 학생 수: {len(safe_students.get('students', []))}")
마무리
JSON은 현대 웹 개발과 데이터 교환에서 필수적인 형식입니다. Python의 json
모듈을 사용하면:
핵심 기능
json.dumps()
: Python 객체 → JSON 문자열json.loads()
: JSON 문자열 → Python 객체json.dump()
: Python 객체 → JSON 파일json.load()
: JSON 파일 → Python 객체
중요 옵션
indent=2
: 들여쓰기로 가독성 향상ensure_ascii=False
: 한글 등 non-ASCII 문자 그대로 유지sort_keys=True
: 키를 알파벳 순으로 정렬