직렬화는 데이터를 효과적으로 저장하고 전송하는 데 필수적인 역할을 하며, 복잡한 데이터 구조를 간단한 형태로 변환하는 데에도 중요합니다.
- 데이터 전송과 저장의 용이성 , 데이터 통합 및 교환 용이성
import 'dart:convert';
// api에서 내려오는 데이터를 가정하에 jsonStr에 데이터를 기입하였습니다.
void main() {
// 1. JSON 문자열 정의
String jsonStr = '{"name": "John", "age": 30, "email": "john@example.com"}';
// 2. JSON Decode: JSON 문자열을 Map 구조로 변환, decode 변환 : json.decode 메소드를 사용하여 Dart의 Map<String, dynamic> 구조로 변환
Map<String, dynamic> userMap = json.decode(jsonStr);
// 3. fromJson 메소드: Map 구조를 사용하여 User 객체 생성
User user = User.fromJson(userMap);
// User 객체 사용 예시
print('Name: ${user.name}');
print('Age: ${user.age}');
print('Email: ${user.email}');
}
// 📎 아래 클래스는 보통 페이지를 별로도 구현합니다.
class User {
String name;
int age;
String email;
User({required this.name, required this.age, required this.email});
factory User.fromJson(Map<String, dynamic> json) {
return User(
name: json['name'],
age: json['age'],
email: json['email'],
);
}
}
//출력
I/flutter (13835): Name: John
I/flutter (13835): Age: 30
I/flutter (13835): Email: john@example.com
import 'package:http/http.dart' as http;
import 'dart:convert';
// User 클래스 정의
class User {
String name;
int age;
String email;
User({this.name, this.age, this.email});
factory User.fromJson(Map<String, dynamic> json) {
return User(
name: json['name'],
age: json['age'],
email: json['email'],
);
}
}
void fetchUserData() async {
final response = await http.get(Uri.parse('https://example.com/user'));
if (response.statusCode == 200) {
// 서버로부터 받은 JSON 문자열
String jsonStr = response.body;
// JSON 문자열을 Dart 객체로 변환
Map<String, dynamic> userMap = json.decode(jsonStr);
User user = User.fromJson(userMap);
// User 객체의 데이터 출력
print('User Name: ${user.name}');
print('User Age: ${user.age}');
print('User Email: ${user.email}');
} else {
// 서버에서 에러 응답을 받은 경우 처리
print('Failed to load user data');
throw Exception('Failed to load user data');
}
}
void main() {
fetchUserData();
}
Json_json_serialized을 이용하기 위해서는 두개의 패키지를 설치해야 합니다. (pubdev)
1. json_annotation: ^4.8.1 - dependencies에 패키지를 설치합니다.
2.json_serializable: ^6.7.1 - dev_dependencies에 설치합니다. 빌드 할때 한번만 이용하기 때문
import 'package:json_annotation/json_annotation.dart';
part 'user.g.dart'; // 자동 생성될 파일
@JsonSerializable()
class User {
String name;
int age;
String email;
User({this.name, this.age, this.email});
// json_serializable에서 제공하는 메소드
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
Map<String, dynamic> toJson() => _$UserToJson(this);
}
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'user.dart'; // User 클래스를 정의한 파일
void fetchUserData() async {
final response = await http.get(Uri.parse('https://example.com/user'));
if (response.statusCode == 200) {
// 서버로부터 받은 JSON 문자열
String jsonStr = response.body;
// JSON 문자열을 Dart 객체로 변환
Map<String, dynamic> userMap = json.decode(jsonStr);
User user = User.fromJson(userMap);
// User 객체의 데이터 출력
print('User Name: ${user.name}');
print('User Age: ${user.age}');
print('User Email: ${user.email}');
} else {
// 서버에서 에러 응답을 받은 경우 처리
print('Failed to load user data');
}
}
받아오는 데이터를 다른 곳에서는 다른 변수값을 설정하고 싶을경우에는 @jsonKey를 이용해야합니다.
받아오는 데이터는 priviewURL 이지만 jsonKey를 통해 custom하여 내부에서는 preiewUrl로 쓰일 수 있습니다.
@JsonKey(name: 'previewURL')
String previewUrl;
예) JsonSerializable 과 freezed의 차이점을 보여주는 코드이고 이용하기 위해서는 JsonSerializable을 삭제합니다.
import 'package:json_annotation/json_annotation.dart';
part 'photo.g.dart';
@JsonSerializable()
class Photo {
int id;
String tags;
@JsonKey(name: 'previewURL')
String previewUrl;
Photo({required this.id, required this.tags, required this.previewUrl});
factory Photo.fromJson(Map<String,dynamic> json) => _$PhotoFromJson(json);
Map<String, dynamic> toJson() => _$PhotoToJson(this);
}
@freezed
class Photo with _$Photo {
factory Photo({
required int id,
required String tags,
required @JsonKey(name: 'previewURL') String previewUrl,
}) = _Photo
factory Photo.fromJson(Map<String, dynamic> json) => _$PhotoFromJson(json);
}
freezed 적용 (build runner 는 JsonSerializable과 동일합니다.)
import 'dart:async';
import 'package:image_search/data/api.dart';
import 'package:image_search/model/photo.dart';
class HomeViewModel {
final PixabayApi api;
final _photoScreamController = StreamController<List<Photo>>()..add([]); //기존 photo를 담아주는 데이터를 없에고 controller로 대체합니다. 최초에는 데이터가 없으므로 circulr가 보이는데 add를 추가하여 빈 값을 출력하게 합니다.
Stream<List<Photo>> get photoStream => _photoScreamController.stream;
HomeViewModel(this.api);
Future<void> fetch(String query) async {
final result = await api.fetch(query);
_photoScreamController.add(result);
}
}