본문 바로가기
Mobile Programming

Flutter(Dart) - Model 객체 Json 매핑 쉽게 하기(@JsonSerializable)

by 맑은안개 2022. 3. 17.

들어가며..

모델객체를 json데이터로 변환, json에서 모델객체로 변환하기 위해 우리는 Model class에 관용적으로 사용되는 fromJson, toJson이름의 함수를 구현한다. 이를 직접만드는 일은 사실 꽤 번거로운 일이고 비생산적이다. Dart 패키지인 json_serializable을 사용하여 이런 번거로운 일을 손쉽게 해결할 수 있다.

개발환경

  • windows 10 ( MacOS 무관 )
  • Visual Studio Code
  • Flutter 2.10 ( Dart만 사용해도 무방하다. )

프로젝트 생성

flutter create exam_json

⚙ pubspec.yaml

dependencies:
  flutter:
    sdk: flutter
  http: ^0.13.4  
  json_annotation: ^4.4.0

dev_dependencies:
  flutter_test:
    sdk: flutter
  build_runner: ^2.0.5
  json_serializable: ^6.1.5
  flutter_lints: ^1.0.0
  • json_annotation, json_serializable은 의존관계를 맺고 있다.

Sample model

샘플모델은 jsonplaceholder에서 제공하는 post 데이터를 기반으로 한다.

[
    {
      "userId": 1,
      "id": 1,
      "title":
          "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
      "body":
          "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
    },
    {
      "userId": 1,
      "id": 2,
      "title": "qui est esse",
      "body":
          "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla"
    }
]

📃 lib/model/post.dart

import 'package:json_annotation/json_annotation.dart';

part 'post.g.dart';

@JsonSerializable()
class Post {
  final int userId;
  final int id;
  final String title;
  final String body;

  Post(this.userId, this.id, this.title, this.body);

  factory Post.fromJson(Map<String, dynamic> json) => _$PostFromJson(json);

  Map<String, dynamic> toJson() => _$PostToJson(this);

  @override
  String toString() {
    return "Post id [${id}] title: $title";
  }
}
  • 아직 post.g.dart가 생성되기 전이므로 에디터에서는 오류로 인식하고 있으나 무시한다.
  • PostFromJson, PostToJson 또한 마찬가지로 자동생성 되므로 무시한다.

⌨ build_runner 실행

flutter pub run build_runner build
  • build_runner를 실행하여 @JsonSerializable로 지정된 class의 json매핑함수(PostFromJson, PostToJson)을 실행한다.
  • part 'post.g.dart'로 지정한 파일이 모델 디렉토리에 생성된다.
  • post클래스의 필드 속성이 변경되면 빌드를 다시 실행해야 한다.

💻 결과

[INFO] Generating build script...
[INFO] Generating build script completed, took 304ms

[INFO] Precompiling build script......
[INFO] Precompiling build script... completed, took 4.7s

[INFO] Initializing inputs
[INFO] Building new asset graph...
[INFO] Building new asset graph completed, took 810ms

[INFO] Checking for unexpected pre-existing outputs....
[INFO] Checking for unexpected pre-existing outputs. completed, took 0ms

[INFO] Running build...
[INFO] Generating SDK summary...
[INFO] 3.4s elapsed, 0/4 actions completed.
[INFO] Generating SDK summary completed, took 3.4s

[INFO] 4.5s elapsed, 0/4 actions completed.
[INFO] 5.6s elapsed, 0/4 actions completed.
[INFO] 10.4s elapsed, 1/4 actions completed.
[INFO] Running build completed, took 11.0s

[INFO] Caching finalized dependency graph...
[INFO] Caching finalized dependency graph completed, took 23ms

[INFO] Succeeded after 11.0s with 2 outputs (9 actions)

📃 post.g.dart 확인

// GENERATED CODE - DO NOT MODIFY BY HAND

part of 'post.dart';

// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************

Post _$PostFromJson(Map<String, dynamic> json) => Post(
      json['userId'] as String,
      json['id'] as String,
      json['title'] as String,
      json['body'] as String,
    );

Map<String, dynamic> _$PostToJson(Post instance) => <String, dynamic>{
      'userId': instance.userId,
      'id': instance.id,
      'title': instance.title,
      'body': instance.body,
    };

👀 Model Test

post.dart에 임시로 main함수를 생성하여 테스트 해보자.

void main() {
  List<dynamic> jsonPosts = [
    {
      "userId": 1,
      "id": 1,
      "title":
          "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
      "body":
          "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
    },
    {
      "userId": 1,
      "id": 2,
      "title": "qui est esse",
      "body":
          "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla"
    }
  ];
}
  • 위와 같이 테스트 데이터를 main함수에 생성한다.

 

⌨ Json -> Model

  // Convert Json to Post model
  List<Post> posts = jsonPosts.map((e) => Post.fromJson(e)).toList();

  print(posts);
  • dart run lib/model/post.dart 명령을 실행한다.
[Post id [1] title: sunt aut facere repellat provident occaecati excepturi optio reprehenderit, Post id [2] title: qui est esse]

⌨ Model -> Json

  // Convert Post model to Json
  Post newPost = Post(1, posts.length + 1, 'New title', 'Hello world!');
  var json = newPost.toJson();
  print(json.toString());
{userId: 1, id: 3, title: New title, body: Hello world!}
반응형