이번 구현은 다음과 같은 방법으로 실시할 예정입니다.
- 필요한 depedency import
- 필요한 Model 생성
- Model에 JsonSerializable 적용하기
- Json 데이터 생성하기
- shared_preferences를 사용하여 Json 데이터 저장하기
- 저장된 Json 데이터를 수정, 삭제 하기
Json 데이터로 저장하기 위해 필요한 Dependency
필요한 Depedency는 다음과 같습니다.
dependencies:
# shared_preferences - https://pub.dev/packages/shared_preferences/install
shared_preferences: ^2.2.3
# json_annotation - https://pub.dev/packages/json_annotation/install
json_annotation: ^4.9.0
# build_runner - https://pub.dev/packages/build_runner/install
build_runner: ^2.4.9
다음은 dev_depedencies에 설치해야하는 패키지입니다.
dev_dependencies:
json_serializable: ^6.6.0
제가 올린 것을 복사해서 사용해도 괜찮고
직접 각각의 Flutter 패키지에 들어가서 버전을 확인하고 설치해도 상관없습니다.
참고로 Flutter에 새로운 패키지를 설치, 업데이트할 때 Android Studio에 뜨는 기능은 다음과 같습니다.
- Pub get: pubspec.yaml 파일에 명시된 의존성들을 다운로드하고 설치
- Pub upgrade: 이미 설치된 패키지들을 최신 버전으로 업그레이드하는 데 사용 (pubspec.yaml 파일에서 명시한 버전 범위 내에서)
- Pub outdated: 프로젝트의 의존성 중에서 업데이트가 가능한 패키지들을 확인하는 데 사용
필요한 Model 생성
다음은 예시로 사용할 Model을 정의합니다.
저는 개인 프로젝트에 사용할 모델을 여기서 그대로 사용하겠습니다.
제가 정의한 모델은 다음과 같습니다.
모델이 되는 모든 class에 @JsonSerializable를 붙여줘야합니다.
또한 제일 위에 있는 part 'chat.g.dart';를 반드시 넣어줘야합니다.
import 'package:json_annotation/json_annotation.dart';
part 'chat.g.dart';
@JsonSerializable()
class ChatList {
final List<Chat>? chatList;
ChatList({this.chatList});
}
@JsonSerializable()
class Chat {
// 채팅 타이틀
final String title;
// 채팅 내용
final List<Message> messageList;
// 채팅하고 있는 멤버
final List<Friend> chatMember;
// 채팅에 있는 공지 사항 내용
Noti? notification;
// 해당 채팅의 제일 최근 수정된 날짜 - 메시지만 카운트함
DateTime modifiedDate;
Chat(
{required this.title,
required this.messageList,
required this.chatMember,
required this.modifiedDate});
}
@JsonSerializable()
class Noti {
final String id;
final String message;
Noti({required this.id, required this.message});
}
@JsonSerializable()
class Message {
final String id;
final DateTime messageTime;
final String message;
final MessageType messageType;
final bool isMe;
Message({
required this.id,
required this.messageTime,
required this.message,
required this.messageType,
required this.isMe,
});
}
enum MessageType { message, date, state }
그리고 위 코드에서 사용중인 Friend 모델의 내부는 다음과 같습니다.
Friend 모델의 경우 다른 곳에서 사용하기 위해 손으로 toMap 동작을 구현했습니다.
또한 Chat 모델에서 JsonSerializable()을 사용하고 있기 때문에 Friend에도 해당 어노테이션을 붙여줍니다.
@JsonSerializable()
class Friend {
final String id;
final String name;
String message;
String profileImgPath;
int me;
Friend({
required this.id,
required this.name,
this.message = "",
this.profileImgPath = Strings.defaultProfileImgPath,
this.me = 0
});
Map<String, dynamic> toMap() {
return {
'id': id,
'name': name,
'message': message,
'profileImgPath': profileImgPath,
'me': me
};
}
factory Friend.fromMap(Map<String, dynamic> map) {
return Friend(
id: map['id'],
name: map['name'],
message: map['message'],
profileImgPath: map['profileImgPath'],
me: map['me']
);
}
@override
String toString() {
return "Friend(id: $id, name: $name, message: $message, profileImgPath: $profileImgPath, me: $me)";
}
}
이렇게 하면 일단 Model에 대한 정의는 끝납니다.
이제 해당 Model을 사용해서 필요한 파일을 build합니다.
Model에 JsonSerializable 적용하기
프로젝트의 루트 부분에서 다음과 같은 커맨드를 실행합니다.
dart run build_runner build
그리고 다음과 같이 성공하면 여기까진 문제가 없는 것입니다.
성공한다면 위에서 정의한 Model 파일과 같은 위치에 g.dart라는 파일이 생성된 것을 확인할 수 있습니다.
그 안에는 다음과 같이 되어있습니다.
이제 자동으로 생성된 g.dart 파일을 각각의 모델에 적용합니다.
적용된 chat.dart의 모습은 다음과 같습니다.
import 'package:json_annotation/json_annotation.dart';
part 'chat.g.dart';
@JsonSerializable()
class ChatList {
final List<Chat>? chatList;
ChatList({this.chatList});
factory ChatList.fromJson(Map<String, dynamic> json) => _$ChatListFromJson(json);
Map<String, dynamic> toJson() => _$ChatListToJson(this);
}
@JsonSerializable()
class Chat {
// 채팅 타이틀
final String title;
// 채팅 내용
final List<Message> messageList;
// 채팅하고 있는 멤버
final List<Friend> chatMember;
// 채팅에 있는 공지 사항 내용
Noti? notification;
// 해당 채팅의 제일 최근 수정된 날짜 - 메시지만 카운트함
@JsonKey(fromJson: _fromJson, toJson: _toJson)
DateTime modifiedDate;
Chat(
{required this.title,
required this.messageList,
required this.chatMember,
required this.modifiedDate});
factory Chat.fromJson(Map<String, dynamic> json) => _$ChatFromJson(json);
Map<String, dynamic> toJson() => _$ChatToJson(this);
static DateTime _fromJson(int millisecondsSinceEpoch) =>
DateTime.fromMillisecondsSinceEpoch(millisecondsSinceEpoch);
static int _toJson(DateTime date) => date.millisecondsSinceEpoch;
}
@JsonSerializable()
class Noti {
final String id;
final String message;
Noti({required this.id, required this.message});
factory Noti.fromJson(Map<String, dynamic> json) => _$NotiFromJson(json);
Map<String, dynamic> toJson() => _$NotiToJson(this);
}
@JsonSerializable()
class Message {
final String id;
final DateTime messageTime;
final String message;
final MessageType messageType;
final bool isMe;
Message({
required this.id,
required this.messageTime,
required this.message,
required this.messageType,
required this.isMe,
});
factory Message.fromJson(Map<String, dynamic> json) => _$MessageFromJson(json);
Map<String, dynamic> toJson() => _$MessageToJson(this);
}
enum MessageType { message, date, state }
chat.dart에 추가한 각각의 코드의 의미는 다음과 같습니다.
@JsonKey(fromJson: _fromJson, toJson: _toJson)
final DateTime modifiedDate;
@JsonKey 어노테이션은 json_annotation 패키지에서 제공하는 기능으로 JSON의 직렬화 / 역직렬화 방식을 커스텀할 때 사용한다.
@JsonKey 어노테이션은 다음과 같은 두 매개변수를 받을 수 있다.
- fromJson: JSON 데이터를 역직렬화 할 때 사용할 함수를 지정
- toJson: JSON 데이터를 직렬화 할 때 사용할 함수를 지정
@JsonKey에 사용되는 직렬화 / 역직렬화 함수는 다음과 같습니다
static DateTime _fromJson(int millisecondsSinceEpoch) =>
DateTime.fromMillisecondsSinceEpoch(millisecondsSinceEpoch);
static int _toJson(DateTime date) => date.millisecondsSinceEpoch;
- millisecondsSinceEpoch는 UNIX 타임스탬프로, 1970년 1월 1일 00:00:00 UTC 이후 경과된 밀리초를 나타냅니다.
- 즉, 해당 경과된 밀리초를 사용하여 DateTime으로 데이터를 반환합니다.
factory Chat.fromJson(Map<String, dynamic> json) => _$ChatFromJson(json);
Map<String, dynamic> toJson() => _$ChatToJson(this);
dart의 factory를 사용하여 생성자를 만든다.
각각 Chat 객체를 JSON 데이터로 변환하거나 JSON 데이터를 Chat 객체로 변환할 때 사용한다.
마찬가지로 Friend Model 부분도 Chat Model 처럼 변경해준다.
import 'package:json_annotation/json_annotation.dart';
part 'friend.g.dart';
@JsonSerializable()
class Friend {
final String id;
final String name;
String message;
String profileImgPath;
int me;
Friend({
required this.id,
required this.name,
this.message = "",
this.profileImgPath = Strings.defaultProfileImgPath,
this.me = 0
});
Map<String, dynamic> toMap() {
return {
'id': id,
'name': name,
'message': message,
'profileImgPath': profileImgPath,
'me': me
};
}
factory Friend.fromMap(Map<String, dynamic> map) {
return Friend(
id: map['id'],
name: map['name'],
message: map['message'],
profileImgPath: map['profileImgPath'],
me: map['me']
);
}
@override
String toString() {
return "Friend(id: $id, name: $name, message: $message, profileImgPath: $profileImgPath, me: $me)";
}
factory Friend.fromJson(Map<String, dynamic> json) => _$FriendFromJson(json);
Map<String, dynamic> toJson() => _$FriendToJson(this);
}
다음 포스팅에서는 위에서 생성한 코드를 사용하여
간단하게 JSON 데이터를 생성하고 JSON에서 데이터를 가져오는 방법에 대해 알아보겠습니다.
'플러터(flutter)' 카테고리의 다른 글
Flutter 에러 발생 No connected devices found 해결 방법 (0) | 2024.06.07 |
---|---|
플러터의 Sqlite를 riverpod의 Provider로 사용하기 - 1 (0) | 2024.04.23 |
플러터에서 Firebase Message 사용하기 for Android (1) | 2024.01.26 |
플러터에서 Firebase SDK를 사용하여 로그인 상태 처리 (0) | 2024.01.08 |
플러터에서 Firebase SDK를 사용해서 로그인 인증하기 (0) | 2024.01.06 |
"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."
댓글