본문 바로가기
플러터(flutter)

플러터에서 Json 형태로 데이터 저장하기-1

by 기계공학 주인장 2024. 5. 9.
반응형

이번 구현은 다음과 같은 방법으로 실시할 예정입니다.

 

  1. 필요한 depedency import
  2. 필요한 Model 생성
  3. Model에 JsonSerializable 적용하기
  4. Json 데이터 생성하기
  5. shared_preferences를 사용하여 Json 데이터 저장하기
  6. 저장된 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에서 데이터를 가져오는 방법에 대해 알아보겠습니다.

 

 

반응형


"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."


댓글