📥
firestoreから取得したデータをモデルに変換する
やりたいこと
firestoreから取得したデータをfreezedで作成したデータモデルに変換する。
対応方法
firestoreに用意されているwithConverter()
というメソッドでうまいこと変換できました。
withConverter()
の使い方
以下の様にfirestoreのqueryに繋げて呼び出します。
FirebaseFirestore.instance.collection("categories").withConverter(
fromFirestore: Category.fromFirestore,
toFirestore: (Category model, _) => model.toFirestore(),
);
引数で、データモデルへ相互変換する関数を渡します。
- fromFirestore:
DocumentSnapshot<Map<String, dynamic>>
からデータモデルへの変換 - toFirestore: データモデルから
Map<String, dynamic>
への変換
変換関数の定義
変換関数はwithConverter()
内でベタ書しても動作しますが、データモデルの定義内で実装することで、コードの凝集性を高められます。
以下の通り、データモデルを生成するファクトリ(fromFirestore)とMap型へ変換するメソッド(toFirestore)を追加しました。
単純にデータモデルに変換すると、ドキュメントのIDが参照できないので、fromFirestore内で付与しています。
class Category with _$Category {
const Category._(); // ←Point!!
const factory Category({
String? id,
required String name,
}) = _Category;
factory Category.fromJson(Map<String, dynamic> json) =>
_$CategoryFromJson(json);
// ↓ここから下を追加
factory Category.fromFirestore(
DocumentSnapshot<Map<String, dynamic>> snapshot,
_,
) {
final data = snapshot.data();
return Category(
id: snapshot.id,
name: data?['name'],
);
}
Map<String, dynamic> toFirestore() {
return {
"name": name,
};
}
}
補足
上記ではモデルにIDの付与を行いましたが、もしデータの中身に対して特別な処理が要らなければ、freezedで自動生成されるfromJson/toJsonをwithConverterから呼び出せば、データモデルへの修正なしで実現できます。
FirebaseFirestore.instance.collection("categories").withConverter(
fromFirestore: (DocumentSnapshot<Map<String, dynamic>> snapshot, _) =>
Category.fromJson(snapshot.data()!),
toFirestore: (Category model, _) => model.toJson(),
);
参考情報
Discussion