1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Flutter Freezedとjson_serializable

Last updated at Posted at 2022-09-22

FreezedModelを自動生成するとイミュータブル(状態を変えることができないオブジェクト)でスッキリしたコードを書くことができます。Modelクラスを作成するのにDartのMap(Jsonのハッシュ)を単位毎に一つずつ作る必要があり、定義したあとjson_serializable(コードジェネレータ)を走らせれば、JSONデコード処理(fromJsonメソッド)とエンコード処理(toJsonメソッド)によって自動生成が行われます。Jsonの文字列をDartのデータ型で扱うためにはただの文字列だと使えないのでデコードしてMapのクラス型にする必要があります。実際にコードにして試してみたのがこちら!

コンストラクタ(メンバ変数を初期化する作業)やプロパティ(属性)を定義することに加え、

@override で上書きできるメソッド

// オブジェクトを文字列で表現してくれる。静的(parse)な関数int.parseなどが一緒になったクラスを文字列としてテキストに表現する
.toString()

// 二つの値を比較して等しければ「真」(true)を、等しくなければ「偽」(false)を返す
operator(演算子) == (等価演算子) 

// オブジェクト毎に存在し、== で比較して同じであればtrueを返す
.hashCode

// nullを割り当てれるオブジェクトを複製できるメソッド
.copyWith

// Mapクラス内のjsonを解析してデコード処理
.fromJson

// Mapへのエンコード処理
.toJson

などのメソッドも一緒に定義できるので慣れてしまえばとても役に立つと思います。

必要なパッケージ

pubspec.yaml
dependencies:
  flutter:
    sdk: flutter

  freezed_annotation: ^X.X.X (freezedのアノテーション)
  freezed: ^X.X.X
  build_runner: ^X.X.X (コードジェネレーターの実行)
  json_annotation: ^X.X.X
  json_serializable: ^X.X.X (デコード・エンコードの処理)

生成したファイルと同じディレクトリに内に作成し警告を無くす処理

analysis_options.yaml
analyzer:
  exclude:
    - "**/*.g.dart"
    - "**/*.freezed.dart"
  errors:
    invalid_annotation_target: ignore

コードジェネレーターでビルドするコマンド

Flutterプロジェクト

flutter pub run build_runner build

生成されたファイルが既に存在し、コンフリクトエラーになってしまう場合は

flutter pub run build_runner build --delete-conflicting-outputs

Dartプロジェクト

dart pub run build_runner build

ドキュメントにあるコードで検証

test.dart
// This file is "main.dart"
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:flutter/foundation.dart';

// required: associates our `main.dart` with the code generated by Freezed
part 'test.freezed.dart';
// optional: Since our Person class is serializable, we must add this line.
// But if Person was not serializable, we could skip it.
part 'test.g.dart';

@freezed
class Person with _$Person {
  const factory Person({
    required String firstName,
    required String lastName,
    required int age,
  }) = _Person;

  factory Person.fromJson(Map<String, Object?> json)
      => _$PersonFromJson(json);
}

詳細

  • test.dartファイルを作成しPersonクラスをコーディング

  • part 'test.freezed.dart';part 'test.g.dart';のファイルを作成

  • インスタンス化(初期値の設定)する際に、新しいインスタンスを必ずしも返えさなくて良いfactoryコンストラクタを採用

  • プロパティを必須項目にする場合は型の前にrequiredを置く(null非許容)

  • fromJsonでJSON相互変換用のfactoryコンストラクタを作成

ジェネレーターを実行↓

スクリーンショット 2022-09-22 12.52.54.png
test.dartファイルの並びにtest.freezed.dartファイルとtest.g.dartファイルが生成されました。

その他機能

  • モデルで変更可能なプロパティを定義したい場合@freezed注釈を@unfreezedに変える
@unfreezed
class Person with _$Person {
  factory Person({
    required String firstName,
    required String lastName,
    required final int age,
  }) = _Person;

  factory Person.fromJson(Map<String, Object?> json)
      => _$PersonFromJson(json);
}
  • null許容型(元の型の値の変わりにnullの値を取れる型)
String? firstName,
  • デフォルト値を設定
@Default('ume') String firstName,
  • @JsonKeyでメンバ変数名を変更する
@JsonKey(name: "first_name") String firstName,
  • 非推奨で定義したい場合
@deprecated bool isName,
  • Assert(メソッド外に定義されているメンバ変数"{"X"}"の条件を定義)を利用し入ってきた値が空の場合はエラーを出す
abstract class Person with _$Person {
  @Assert('firstName.isNotEmpty', 'firstNameプロパティはnullを引数に渡せません')
  @Assert('lastName.isNotEmpty', 'lastName cannot be empty')
  @Assert('age >= 0')
  factory Person({
    String? firstName,
    String? lastName,
    int? age,
  }) = _Person;
}
1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?