1. JSON 이란?
Dart 코드로 되어있는 객체를 다른 언어로 작성한 언어 및 플랫폼(ex. 자바로 작성된 서버)에서 작동하게 하려면?
-> 통일된 규격으로 변환하는 작업이 필요: 직렬화
-> 해당 작업을 JSON이라고 함!
- JavaScript Object Notation
- 자바 스크립트의 객체 표기 방식을 기반한다.
- JS Object: 중괄호 안에 Key - Value 쌍
- Key는 반드시 문자열
- Value에 들어갈 수 있는 타입
- String
- Number(int, double)
- Boolean(bool)
- Array(대괄호)
- Object(중괄호)
- null
2. Dart에서의 사용법
- 데이터를 주고 받을 때 JSON 형식의 String으로 주고 받음
- 직렬화: Dart 객체 -> Map -> String
- 역직렬화: String -> Map -> Dart 객체
- Map을 거치는 이유: 객체를 바로 String으로 변환 하려면 개발가가 직접 구현해야함 ⇒ 복잡
- 다트SDK 의 dart:convert 라이브러리에 jsonEncode , jsonDecode 함수가 있는데 Map, List 를 String으로 변환해주거나 Map, List 를 String 등으로 변환해줌
- JSON의 루트, 즉 최상위는 리스트가 될 수 있음. 즉 대괄호 [ ] 가 될 수 있음
JSON은 데이터 포장 규칙,
인코딩은 포장하는 과정, 디코딩은 포장을 뜯는 과정이다.
1) 직렬화
: 객체(앱에서 쓰는 데이터) -> 문자열(JSON)로 바꾸는 것
why?
- 인처넷으로는 객체를 그대로 못 보냄
- 그래서 글자(String)로 바꿔서 보냄
User user = User(name: '유나', age: 25);
-> 직렬화 하면
{"name":"유나","age":25}
2) 역직렬화
: 문자열(JSON) -> 객체(앱에서 쓰는 데이터)로 바꾸는 것
why?
- 서버에서 받은 건 글자 덩어리
- 앱에서는 객체여야 쓰기 편함
{"name":"유나","age":25}
-> 역직렬화하면
User user = User.fromJson(json);
[한 장 정리][앱 객체]
↓ 직렬화
[JSON 문자열]
↓ 네트워크
[JSON 문자열]
↓ 역직렬화
[앱 객체]
정리하자면..
직렬화: 객체를 JSON 형태의 문자열로 변환할 때
- 객체 -> Map -> String
- jsonEncode
- 객체에 toJson 메서드 구현
역직렬화: JSON 형태의 문자열을 객체로 변환할 때
- String -> Map -> 객체로 바꿔준다
- String -> Map: jsonDecode 함수
- Map -> 객체: 객체에 fromJson named 생성자를 구현해서 사용!
사용해보기!
-전체 코드
import 'dart:convert'; //라이브러리 호출
void main() {
String jsonString = """
{
"name": "이지원",
"age": 20
}
""";
var jsonMap = jsonDecode(jsonString);
User user = User.fromJson(jsonMap);
print(user.toJson()); // {name: 이지원, age: 20}
}
class User {
User({
required this.name,
required this.age,
});
String name;
int age;
User.fromJson(Map<String, dynamic> map)
: this(
name: map['name'],
age: map['age'],
);
Map<String, dynamic> toJson() {
return {
"name": name,
"age": age,
};
}
}
1) JSON 형태의 '문자열', 네트워크로 주고 받는 데이터는 보통 이런 "문자열"형태로 옴
void main() {
String jsonString = """
{
"name": "이지원",
"age": 20
}
""";
2) jsonDecode는 JSON 문자열을 다트에서 쓸 수 있는 구조(Map/List)로 바꿈
- 현재 JSON은 { }이므로 결과는 Map이 됨
- jsonDecode의 반환 타입은 상황에 따라 Map일 수도, List일 수도 있어서 보통 dynamic/var로 받는 경우가 많음
- jsonMap은 그냥 Map이라서 jsonMap['name'] 이런 식으로 매번 꺼내야 하지만, 보통 user.name, user.age처럼 명확한 객체로 다루는 게 훨씬 편하고 안전함
var jsonMap = jsonDecode(jsonString);
User user = User.fromJson(jsonMap);
print(user.toJson()); // {name: 이지원, age: 20}
}
3) User 클래스는 앱 안에서 “유저 데이터”를 다루는 설계도
이게 없을 시
- 데이터가 전부 Map<String, dynamic>으로 떠다니고
- 키 오타('naem') 나면 런타임에서 터지고
- 어디서 어떤 데이터가 들어오는지 추적이 어려워짐
User가 있으면:
- user.name처럼 자동완성 됨
- 타입이 고정돼서 실수 줄어듦
- 코드가 읽기 쉬워짐
class User {
User({
required this.name,
required this.age,
});
String name;
int age;
4) 이 Map으로 User를 만들어줘”라는 특수 생성자
- map['name'] → name 필드에 넣고
- map['age'] → age 필드에 넣어서
- 결국 User(name: ..., age: ...) 일반 생성자를 호출해 객체를 완성함
this를 쓰는 이유?
- “초기화는 한 곳에서만” 하게 만들어서 코드 중복을 줄인다.
- 즉, User를 만드는 규칙을 한 군데로 통일하는 거야.
User.fromJson(Map<String, dynamic> map)
: this(
name: map['name'],
age: map['age'],
);
5) toJson은 반대로 User 객체 → Map(JSON 형태)로 변환(직렬화)
- 서버로 보낼 때는 객체(User)를 그대로 못 보냄
- 보낼 수 있는 건 보통 JSON 형태(Map → jsonEncode → String)
Map<String, dynamic> toJson() {
return {
"name": name,
"age": age,
};
}
}'플러터 앱 개발' 카테고리의 다른 글
| Chapter 15. 효율적인 앱 개발을 위한 스로틀링과 디바운싱 (0) | 2026.01.29 |
|---|---|
| Chapter 14. 사용자 경험을 올려주는 애니메이션 (0) | 2026.01.28 |
| [트러블 슈팅] 1차 MVP 제작: Make를 사용하여 모듈 연결 (0) | 2026.01.19 |
| [코드 뜯어보기] 쇼핑몰 앱 만들기 B (1) | 2026.01.16 |
| Chapter 12. 예외 처리 (1) | 2026.01.13 |