[057] 플러터 (Flutter) 배우기 - JSON Serializable (직렬화) 사용

2023. 4. 21. 17:18모바일어플개발/Flutter

반응형

안녕하세요~ totally 개발자입니다.

 

JSON Serializable

 

이 포스팅에서는 JSON Serializable(직렬화)에 대해 다뤄봅니다. 보통 예전 포스팅에서 주로 사용했던 dart:convert를 이용하는 수동 직렬화와 오늘 포스팅에서 사용할 라이브러리를 사용해서 자동으로 직렬화하는 방법이 있습니다. 수동 직렬화는 세팅을 하지 않고 간단하게 구현할 수 있다는 장점이 있어 소규모의 프로젝트로는 괜찮을 수 있으나 어느 정도 프로젝트의 규모가 커지고 에러가 발생했을 때 컴파일 과정에서 발견되기 때문에 오류 해결에 있어 더 도움이 됩니다. 간단한 예제를 통해 실습을 해보도록 하겠습니다.

 

Step 1: 다음처럼 build_runner, json_annotation를 적고 dev_dependencies 아래에 json_serializable을 추가합니다.

 

 

 

Step 2: album.dart를 만들고 아래처럼 작성해줍니다. 저는 이미 album.g.dart도 추가해준 상태라 에러가 없지만 따라오시는 분들은 아직 에러가 나올 것입니다.

 

 

Step 3: 터미널에 flutter pub run build_runner build --delete-conflicting-outputs 명령어를 입력합니다.

 

 

 

Step 4: 다음처럼 album.g.dart 코드가 잘 생기면 성공입니다.

 

 

 

Step 5: main.dart에 다음처럼 import 해줍니다.

 

 

 

Step 6: 다음처럼 album 데이터를 받아올 수 있도록 합니다. 이 부분은 수동으로 했을 때와 다른 점은 없습니다.

 

 

 

Step 7: FutureBuilder를 통해 데이터를 가져올 수 있도록 합니다.

 

 

 

Step 8: 아래처럼 결과가 도출되면 성공입니다.

 

 

[전체 소스 코드]

 

[album.dart]

 

import 'package:json_annotation/json_annotation.dart';
part 'album.g.dart';
@JsonSerializable()
class Album {
final int userId;
final int id;
final String title;
Album(this.userId, this.id, this.title);
factory Album.fromJson(Map<String, dynamic> json) => _$AlbumFromJson(json);
Map<String, dynamic> toJson() => _$AlbumToJson(this);
}
view raw 057_album.dart hosted with ❤ by GitHub

 

 

[album.g.dart]

 

// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'album.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
Album _$AlbumFromJson(Map<String, dynamic> json) => Album(
json['userId'] as int,
json['id'] as int,
json['title'] as String,
);
Map<String, dynamic> _$AlbumToJson(Album instance) => <String, dynamic>{
'userId': instance.userId,
'id': instance.id,
'title': instance.title,
};

 

 

[main.dart]

 

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:project/album.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const MaterialApp(
title: "Flutter App",
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
late Future<List<Album>> _albumList;
@override
void initState() {
super.initState();
_albumList = _getAlbumList();
}
Future<List<Album>> _getAlbumList() async {
final response = await http
.get(Uri.parse('https://jsonplaceholder.typicode.com/albums'));
final List<Album> result = jsonDecode(response.body)
.map<Album>((data) => Album.fromJson(data))
.toList();
return result;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Flutter App'),
),
body: Center(
child: FutureBuilder(
future: _albumList,
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data!.length,
itemBuilder: (context, index) {
return Container(
padding: const EdgeInsets.all(15),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("User ID: ${snapshot.data![index].userId}"),
Text("ID: ${snapshot.data![index].id}"),
Text("Title: ${snapshot.data![index].title}"),
],
),
);
},
);
} else {
return const Center(
child: CircularProgressIndicator(
strokeWidth: 2,
),
);
}
},
),
),
);
}
}
view raw 057_main.dart hosted with ❤ by GitHub

 

 

반응형