ネストしたFreezedクラスにまとめてtoJsonを適用したい!
結論
freezedクラスのファクトリコンストラクタに対して@JsonSerializable(explicitToJson: true)
のアノテーションを行う。クラス宣言に対してではない。
はじめに
Flutterでイミュータブルなデータクラスを簡単に作ることができるFreezedでは、Freezedデータクラスをプロパティにもつ、Freezedデータクラスを定義したくなることがあります。
しかし、デフォルトの状態ではそのようなデータクラスに対してtoJson()
を呼び出しても、すべてがMapオブジェクトとしてJSONのような構造に変換されるわけではなく、Freezedデータクラスを値としてもつMapが生成されます。
そのため、たとえばFreezedデータクラスにtoJson()
した結果をそのままFirestoreに保存するユースケースにおいて、データクラスのネストがあった場合にエラーが発生します。
// すみません!コード例は参考記事を見てみてください!
// コメント等で要望がありましたら、きちんとコード例も記述しようと思います。
解決策
Freezedデータクラスの定義コードにおいて、ファクトリコンストラクタのすぐ上に@JsonSerializable(explicitToJson: true)
と書くことで、ネストにも対応することができます[1]。
実際に生成されたコードを覗いてみると、toJson()
を明示的に呼び出す処理が書かれていることがわかります。
// すみません!コード例は参考記事を見てみてください!
// コメント等で要望がありましたら、きちんとコード例も記述しようと思います。
注意点
アノテーションはクラス定義の上に置きたくなりますが、ファクトリコンストラクタの上です!
const factory
の上に@JsonSerializable(explicitToJson: true)
をおいたら、IDEからThe annotation 'JsonSerializable' can only be used on classes.
という警告メッセージが表示されますが、これはバグなのだそうでIssueとして認識されているようです[2]。
実際、クラス定義の上にこのアノテーションを書いてコード生成すると、: Error: Can't use '_$FooBarFromJson' because it is declared more than once.
のようなエラーが発生します[2:1]。
参考記事
-
クラス宣言の上にアノテーションを書いた場合のエラー事例。IDEが間違った警告を出すことについては"This is a known issue/limitation"といわれている。
https://stackoverflow.com/questions/71515619/generated-class-from-freezed-creates-duplicate-fromjson-method_ ↩︎ ↩︎
Discussion