概要
どうも、@daiki1003です!前著JsonKeyチートシートがそこそこ好評だったでした。


そのため、freezedも需要あるのではと思い、書いてみました!
・freezed使ってるけど、使いこなせてる感じはしない
・freezedのoptionって何があるかわかっていない
と言う方に向けてわかりやすく解説したいと思うのでぜひご覧いただければと思います。
執筆時環境
| 名前 | バージョン |
| Flutter | 3.7.12 |
| freezed | 2.3.2 |
unionKey
Unionをシリアライズ/デシリアライズする際に使用するキーを指定します。
デフォルトは、runtimeTypeです。
class Union with _$Union {
factory Union.first() = _First;
factory Union.second() = _Second;
factory Union.fromJson(Map<String, Object> json) => _$UnionFromJson(json);
}
とした定義があるとします。
この時、jsonをパースしようとすると
{'runtimeType': 'first'} // Union.first
{'runtimeType': 'second'} // Union.second
となるのですが、
@Freezed(unionKey: 'type')
class Union with _$Union {
// ...
}
とすることで、
{'type': 'first'} // Union.first
{'type': 'second'} // Union.second
となります。
toJsonの出力も同様に変化します。
unionValueCase
Unionをシリアライズ/デシリアライズする際に、バリューの命名規則について指定します。
先ほどの実装を
@Freezed(unionValueCase: FreezedUnionCase.snake)
class Union with _$Union {
// ...
}
とすることで、
{'runtime_type': 'first'} // Union.first
{'runtime_type': 'second'} // Union.second
となります。
fallbackUnion
Unionが正しくデシリアライズできなかった場合に、代わりに使用するUnionを指定します。
@Freezed(fallbackUnion: 'first')
class Union with _$Union {
// ...
}
とすることで、
{'runtimeType': 'first'} // Union.first
{'runtimeType': 'second'} // Union.second
{'runtimeType': 'third'} // Union.first
となります。
copyWith
copyWithを生成するかどうかを指定します。
デフォルトは、trueです。
もし、nullなら、build.yamlの値を見に行きます。
それもnullなら、デフォルト値のtrueが採用されます。
equal
==/hashcodeを生成するかどうかを指定します。
デフォルトは、nullです。
もし、nullなら、build.yamlの値を見に行きます。
それもnullなら、独自に==が実装されていない場合のみ==/hashcodeが生成されます。
toStringOverride
toStringを生成するかどうかを指定します。
デフォルトは、nullです。
もし、nullなら、build.yamlの値を見に行きます。
それもnullなら、独自にtoStringが実装されていない場合のみtoStringが生成されます。
fromJson
fromJsonを生成するかどうかを指定します。
デフォルトは、nullです。
もし、nullなら、build.yamlの値を見に行きます。
それもnullなら、対象のクラスがfromJsonを
@freezed
class Example with _$Example {
factory Example(int a) = _Example;
factory Example.fromJson(Map<String, Object?> json) => _$ExampleFromJson(json);
}
の様に、実装している場合のみ生成します。
逆に、以下の様に実装している場合は、生成されません。
@freezed
class Example with _$Example {
factory Example(int a) = _Example;
factory Example.fromJson(Map<String, Object?> json) {
// `=>` ではなく `{ return }` を使っているため生成されない
return {...};
}
}
—
と、書いてはいるのですが、実際に何をreturnすればいいのか、現状わかっていません。
詳しい人教えてください🙏
toJson
toJsonを生成するかどうかを指定します。
デフォルトは、nullです。
もし、nullなら、build.yamlの値を見に行きます。
それもnullなら、対象のクラスがfromJsonを
@freezed
class Example with _$Example {
factory Example(int a) = _Example;
factory Example.fromJson(Map json) => _$ExampleFromJson(json);
}
の様に、実装している場合のみ生成します。
逆に、以下の様に実装している場合は、生成されません。
@freezed
class Example with _$Example {
factory Example(int a) = _Example;
factory Example.fromJson(Map<String, Object?> json) {
// `=>` ではなく `{ return }` を使っているため生成されない
return {...};
}
}
—
と、ここまで全くfromJsonと同じ説明を書いていますが間違いではありません。fromJson/toJsonはペアの存在ですので、fromJsonの有無はtoJsonの有無に一致する様になっているのです。
map
map、mapOrNull, maybeMapメソッドを
それぞれ生成するかを指定できます。
FreezedMapOptionはコメントアウト部分を除くと以下のような定義になっています。
class FreezedMapOptions {
const FreezedMapOptions({
this.map,
this.mapOrNull,
this.maybeMap,
});
factory FreezedMapOptions.fromJson(Map json) =>
_$FreezedMapOptionsFromJson(json);
static const all = FreezedMapOptions(
map: true,
mapOrNull: true,
maybeMap: true,
);
static const none = FreezedMapOptions(
map: false,
mapOrNull: false,
maybeMap: false,
);
final bool? map;
final bool? mapOrNull;
final bool? maybeMap;
}
それぞれ生成するかどうかを指定できます。
デフォルトはnullです。
もし、nullなら、build.yamlの値を見に行きます。
それもnullなら、FreezedMapOptions.all、つまり全部生成する様になります。
—
個人的には、mapOrNullやmaybeMapはunionの良さを一つ消してしまうので、mapのみの生成が良いと思っています。
理由としては、 orElseなどの「その他」と言う指定の仕方をしてしまうと新しい要素を追加した時にorElseに吸い込まれてしまい、コンパイルも通ってしまうため使用箇所の確認を怠ってしまう可能性があるからです。
この際、build.yamlには以下の様に記述します。
targets:
$default:
builders:
freezed:
options:
map:
map_or_null: false
maybe_map: false
when
when、whenOrNull, maybeWhenメソッドを
それぞれ生成するかを指定できます。
FreezedWhenOptionはコメントアウト部分を除くと以下のような定義になっています。
class FreezedWhenOptions {
const FreezedWhenOptions({
this.when,
this.whenOrNull,
this.maybeWhen,
});
factory FreezedWhenOptions.fromJson(Map json) =>
_$FreezedWhenOptionsFromJson(json);
static const all = FreezedWhenOptions(
when: true,
whenOrNull: true,
maybeWhen: true,
);
static const none = FreezedWhenOptions(
when: false,
whenOrNull: false,
maybeWhen: false,
);
final bool? when;
final bool? whenOrNull;
final bool? maybeWhen;
}
それぞれ生成するかどうかを指定できます。
デフォルトはnullです。
もし、nullなら、build.yamlの値を見に行きます。
それもnullなら、FreezedWhenOptions.all、つまり全部生成する様になります。
—
個人的には、whenOrNullやmaybeWhenはunionの良さを一つ消してしまうので、whenのみの生成が良いと思っています。
理由は、mapの方を参照してください。
この際、build.yamlには以下の様に記述します。
targets:
$default:
builders:
freezed:
options:
when:
when_or_null: false
maybe_when: false
makeCollectionsUnmodifiable
List, Map, SetをそれぞれUnmodifiableListView, UnmodifiableMapView,UnmodifiableSetViewに変換するかを指定できます。
デフォルトはtrueです。
—
なんで接尾辞Viewなんだろう…。
addImplicitFinal
明示的にコンストラクタの引数パラメタにfinalを付与するかを指定できます。
デフォルトはtrueです。
@Freezed(addImplicitFinal: true) // なくても良い
class Person with _$Person {
factory Person(String name, int age) = _Person;
}
は、以下と同義になります。
@Freezed(addImplicitFinal: false)
class Person with _$Person {
factory Person(final String name, final int age) = _Person;
}
genericArgumentFactories
JsonSerializableのgenericArgumentFactoriesの有効/無効を設定します。
デフォルトはfalseです。
fromJson(Map json) => _$ExampleFromJson(json)
を
fromJson(Map<String, Object?> json, T Function(Object?) fromJsonT) => _$ExampleFromJson(json, fromJsonT)
の様に変更します。
@Freezed(genericArgumentFactories: true)
class Example<T> extends _$Example<T> {
factory Example({
required T id,
}) = _Example;
factory Example.fromJson(Map<String, Object?> json, T Function(Object?) fromJsonT) => _$ExampleFromJson(json, fromJsonT);
}
の様な定義が出来る様です。
最後に
いかがでしたでしょうか?
今まで使ったことがないオプションはありましたか?
是非触ってみて、Freezedの手触り感を体験してみてださい!
Twitterフォローお願いします
「次回以降も記事を読んでみたい!」「この辺分からなかったから質問したい!」
そんな時は、是非Twitter (@daiki1003)やInstagram (@ashdik_flutter)のフォローお願いします♪
Twitterコミュニティ参加お願いします
Twitterコミュニティ「Flutter lovers」を開設しました!参加お待ちしております😁
☕️ Buy me a coffee
また、記事がとても役に立ったと思う人はコーヒーを奢っていただけると非常に嬉しいです!



コメント