@JsonSerializable 어노테이션은 Json 데이터를 직렬화/역직렬화(인코딩/디코딩)를 쉽게 처리하기 위한 어노테이션이다.
@JsonSerializable 어노테이션을 사용하면 Json 직렬화 코드를 자동으로 생성한다.
코드의 간결성과 model 데이터가 변경되거나 추가될 때마다 수동으로 업데이트를 해줘야 하는 불편함을 줄어들고 유지보수가 향상된다.
1. json_sericalizable 추가
프로젝트 터미널에 아래 명령어를 입력한다.
flutter pub add json_annotation dev:build_runner dev:json_serializable
pubspec.yaml에 패키지가 추가된 것을 확인할 수 있다.
dependencies:
flutter:
sdk: flutter
json_annotation: ^4.8.1
dev_dependencies:
flutter_test:
sdk: flutter
build_runner: ^2.4.8
json_serializable: ^6.7.1
2. Model 클래스 생성
*.g.dart 에서 * 에는 파일 이름을 적어준다.
*. g.dart 파일은 해당 파일에 필요한 직렬화 및 역직렬화 코드를 추가한다.
이 파일은 자동으로 생성되고 관리되기 때문에 내가 직접 수정하지 않아도 된다.
import 'package:json_annotation/json_annotation.dart';
// 파일 이름.g.dart
part 'color_model.g.dart';
@JsonSerializable()
class ColorModel {
int id;
String name;
int year;
String color;
@JsonKey(name: 'pantone_value')
String pantoneVale;
ColorModel({
required this.id,
required this.name,
required this.year,
required this.color,
required this.pantoneVale
});
// factory constructor : JSON 데이터를 기반으로 ColorModel 인스턴스를 생성하는데 필요하다.
// _$ColorModelFromJson(json) : 주어진 JSON 맵을 이용하여 ColorModel의 객체를 자동으로 생성한다.
factory ColorModel.fromJson(Map<String, dynamic> json) => _$ColorModelFromJson(json);
// ColorModel 객체를 JSON 형태로 직렬화한다.
// _$ColorModelToJson(this) : 해당 객체의 필드들이 JSON 키-값 쌍으로 매핑되어진 Map을 반환
//{
// "name": "Red"
//}
Map<String, dynamic> toJson() => _$ColorModelToJson(this);
}
3. 코드 생성기(Code Generator) 실행
코드 생성기(Code Generator)를 실행하는 방법은 두 가지가 있다.
3.1. One-time code generation
필요할 때마다 모델에 대한 JSON 직렬화 코드를 생성하는 방법이다.
모델 클래스를 변경할 때마다 아래 명령어를 통해 수동으로 빌드를 실행하면 된다.
dart run build_runner build --delete-conflicting-outputs
이 명령어는 build_runner 패키지를 사용하여 소스 코드를 생성하고 필요한 파일들을 빌드하고 충돌이 발생하는 파일들은 삭제해 준다.
3.2. Generating code continuously
프로젝트 파일의 변경 사항을 감시하고 필요할 때 자동으로 필요한 파일들을 빌드한다.
dart run build_runner watch --delete-conflicting-outputs
이 명령어는 한 번 실행한 다음 백그라운드에서 실행되도록 두는 것이 안전하다고 한다.
한 번만 빌드되는 명령어를 실행해 보았다.
dart run build_runner build --delete-conflicting-outputs
에러가 사라지고 color_model.g.dart 파일이 생성되었다.
아래는 생성된 ColorModel.g.dart 파일이다.
// 수정하지 말라고 적혀있다.
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'color_model.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
ColorModel _$ColorModelFromJson(Map<String, dynamic> json) => ColorModel(
id: json['id'] as int,
name: json['name'] as String,
year: json['year'] as int,
color: json['color'] as String,
// @JsonKey 어노테이션을 달았던 것도 잘 매핑되었다.
pantoneVale: json['pantone_value'] as String,
);
Map<String, dynamic> _$ColorModelToJson(ColorModel instance) =>
<String, dynamic>{
'id': instance.id,
'name': instance.name,
'year': instance.year,
'color': instance.color,
'pantone_value': instance.pantoneVale,
};
만약, 중첩된 클래스가 있다면?
클래스 내에 또 다른 클래스가 있다면 잘못된 인자를 넘길 수도 있다고 한다.
다른 Model 클래스 생성해서 테스트를 해보았다.
위 과정과 똑같이 진행했다.
그럼 user_model.g.dart의 _$UserModelToJson()가 이렇게 만들어진다.
보기에는 문제가 없지만 출력해 보면 아래와 같다.
ColorModel colorModel = ColorModel(
id: 2,
name: 'fuchsia rose',
year: 2001,
color: '#C74375',
pantoneVale: '17-2031'
);
UserModel userModel = UserModel('John', colorModel);
print(userModel.toJson());
출력 결과 >
{name: John, colorModel: Instance of 'ColorModel'}
그런데 만약 아래와 같이 출력하고 싶다면,
{
name: John,
colorModel: {
id: 2,
name: fuchsia rose,
year: 2001,
color: #C74375,
pantone_value: 17-2031
}
}
@JsonSerializable 어노테이션에 explicitToJson: true를 전달하면 된다.
@JsonSerializable(explicitToJson: true)
class UserModel {
String name;
ColorModel colorModel;
UserModel(this.name, this.colorModel);
factory UserModel.fromJson(Map<String, dynamic> json) => _$UserModelFromJson(json);
Map<String, dynamic> toJson() => _$UserModelToJson(this);
}
다시 빌드하고 출력하면 ColorModel 클래스의 데이터를 출력할 수 있다.
dart run build_runner build --delete-conflicting-outputs
[참고]
JSON and serialization
How to use JSON with Flutter.
docs.flutter.dev
'Flutter' 카테고리의 다른 글
[Flutter][해결]Android 실행 시 에러(Migration하기) (0) | 2024.03.10 |
---|---|
[Flutter]플러터 업그레이드(강제 업그레이드) (0) | 2024.03.09 |
[flutter][해결]INSTALL_FAILED_INSUFFICIENT_STORAGE (0) | 2024.03.05 |
[Flutter][Localizations]다국어 대응 (0) | 2024.02.19 |
[Flutter]Simulator 동영상 찍기, gif 저장 (0) | 2024.01.18 |