こんにちは。広瀬マサルです。
Google I/O 2024でFlutterのマクロの発表がありましたね。
Masamuneフレームワークは「アプリ開発のすべてをマクロでサポートする」ことを最終的な目標として開発を続けていました。
マクロへの対応を行うためにこれまでfreezedやjson_serializableに頼っていたデータクラスやJsonの変換をMasamuneフレームワーク内で行うことにしました。
使い方をまとめたので興味ある方はぜひ使ってみてください!
💡 2024年6月時点ではDartのマクロ機能はプレビュー版です。
破壊的な変更が続くことが予想されるため当パッケージも仕様が大幅に変更される可能性が高いです。ご注意ください。
katana_value
はじめに
Dartのマクロ機能を利用しイミュータブルなデータクラスの作成を可能にします。
比較演算子
への対応およびcopyWith
の実装、toString
の整備がアノテーションを付与するだけで可能になります。
また合わせてJsonからの変換
、Jsonへの変換
も可能にします。
下記のように簡単に定義可能です。
@DataValue
class Person {
Person({
required String name,
int? age,
});
}
下記のように利用することが可能です。
final person = Person(name: "Kanimiso");
final copied = person.copyWith(age: 20);
final json = person.toJson();
print(json); // {name: "Kanimiso", age: 20}
事前準備
💡 2024年6月時点で必要な準備です。マクロがStableになった場合必要ありません。
-
Dart dev channel もしくは Flutter master channel に変更します。
-
dart --version
を実行しDartのバージョンを3.5.0-152
より新しくします。 -
pubspec.yaml
のDartSDKのバージョンを^3.5.0-152
に設定します。 -
analysis_options.yaml
に下記のコードを追加します。analyzer: enable-experiment: - macros
-
dart run --enable-experiment=macros bin/my_app.dart
インストール
下記パッケージをインポートします。
flutter pub add katana_value
実装
データクラスの作成
@DataValue
のアノテーションをデータクラスにしたいクラスに付与します。
コンストラクタに必要なフィールドの型と名前を定義します。これだけでデータクラスが作成されます。
@DataValue
class Person {
Person({
required String name,
int? age,
});
}
データクラスの利用
定義したクラスはそのままオブジェクト化を行うことができます。
final person = Person(name: "Kanimiso", age: 20);
またcopyWith
やtoJson
、fromJson
などのメソッドを利用することが可能です。
final json = {"name": "Kanimiso", "age": 20};
final person = Person.fromJson(json);
print(person.toString()); // Person(name: Kanimiso, age: 20)
final copied = person.copyWith(age: 30);
print(copied.toJson()); // {"name": "Kanimiso", "age": 30};
Jsonに変換可能な型
初期状態では下記の型が変換可能です。(Nullable含む)
int
double
num
String
bool
Iterable
List
Set
Map
新しいJson変換型への対応
上記の型が初期で利用可能ですが新しくJsonの変換に対応したい型がある場合はDataValueJsonConverter
を利用します。
-
DataValueJsonConverter
を継承したクラスを作成します。class ModelCounterJsonConverter extends DataValueJsonConverter { const ModelCounterJsonConverter(); @override Map<String, dynamic>? toJson(dynamic value) { if (value is ModelCounter) { return value.toJson(); } return null; } @override dynamic fromJson(String key, Map<String, dynamic> json) { final map = json[key]; if(map is Map<String, Object?> && map["#type"] == "ModelCounter") { return PersonBase.fromJson(map); } return null; } }
-
作成したクラスをmainメソッド内などアプリ起動時に
DataValueJsonConverter.register
で登録します。void main(){ DataValueJsonConverter.register(const ModelCounterJsonConverter()); }
実行
💡 2024年6月時点で必要な準備です。マクロがStableになった場合必要ありません。
実行には下記のコマンドを利用します。
dart run --enable-experiment=macros bin/my_app.dart
おわりに
自分で使う用途で作ったものですが実装の思想的に合ってそうならぜひぜひ使ってみてください!
また、こちらにソースを公開しているのでissueやPullRequestをお待ちしてます!
また仕事の依頼等ございましたら、私のTwitterやWebサイトで直接ご連絡をお願いいたします!
GitHub Sponsors
スポンサーを随時募集してます。ご支援お待ちしております!