エキサイトで内定者アルバイトをしている岡島です!
今回はFreezedパッケージを使っていて、階層(入れ子)構造のJSONデータを扱う時につまづいたので解決した対処法を共有します。
Freezedについて
https://pub.dev/packages/freezed
Freezedを使うメリットとして、モデルの定義時にコードの実装量が減り、可読性が上がることが挙げられます。
ドキュメントには以下のような機能の実装が例に挙げられていました。
- コンストラクタ+プロパティの定義
- toString, operator ==, hashCode
- copyWithの実装
- シリアル化、逆シリアル化
- unionやパターンマッチングの機能
Freezedではこのような機能を自動生成してくれるので便利です。
階層(入れ子)構造になっている JSONの扱い方
Freezedで、APIレスポンスのJSONや、modelをFreezed化させたい時、階層構造になっていると単純な実装ではエンコード、デコード時にうまくいきません。
そのような場合の対処について、以下のようなJSONを例に挙げて紹介していこうと思います。
{ "itemName": "扇風機", "detail": { "price": 10000, "description": "心地よい風です。" }, }
このように入れ子になっている場合は、ItemクラスとDeteilクラスのファイルを作り解決します。
Itemクラスの中に itemName と detail のプロパティを作り、detailを price と description のプロパティを持たせたクラスにします。こうすることで、ネスト化されたJSONも問題なく扱うことができます。
以下は完成したItemクラスとDetailクラスです。
import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:my_app/detail.dart'; part 'item.freezed.dart'; part 'item.g.dart'; @freezed class Item with _$Item { factory Item({ required String itemName, required Detail detail, }) = _Item; factory Item.fromJson(Map<String, dynamic> json) => _$ItemFromJson(json); }
import 'package:freezed_annotation/freezed_annotation.dart'; part 'detail.freezed.dart'; part 'detail.g.dart'; @freezed class Detail with _$Detail { factory Detail({ required int price, required String description, }) = _Detail; factory Detail.fromJson(Map<String, dynamic> json) => _$DetailFromJson(json); }
まとめ
Freezedでネスト化されたJSONデータを扱う時は、クラスを分割することでFreezedでも扱うことができるようになりました。 Freezedを使うことで、FromJson/ToJsonやCopyWithのコードを自動生成してくれるのでコードの記述量が非常に軽減されます。
こちらの記事が参考になれば幸いです。
参考記事
https://pub.dev/packages/freezed https://zenn.dev/xxminamixx/scraps/91c01e8efb5cc1