Flutter Firestore v2各类类型withConverter的fromJson/toJson实现示例
使用Firestore v2 withConverter处理数组及全类型对象转换
核心解决:LinkedMap数组转自定义对象列表
Firestore返回的数组会以LinkedHashMap形式存在,在fromJson中需手动遍历数组,将每个LinkedMap转换为对应数据类。以下是覆盖所有常见Firestore类型的完整示例:
1. 定义数据类与Converter
先创建包含Firestore全类型的主数据类,以及嵌套对象的数据类:
import 'package:cloud_firestore/cloud_firestore.dart'; // 嵌套对象数据类 class Address { final String street; final String city; Address({required this.street, required this.city}); factory Address.fromJson(Map<String, dynamic> json) { return Address( street: json['street'] as String, city: json['city'] as String, ); } Map<String, dynamic> toJson() { return { 'street': street, 'city': city, }; } } // 主数据类:覆盖Firestore常见类型 class User { final String id; final String name; final int age; final bool isActive; final Timestamp createdAt; final GeoPoint location; final DocumentReference<Map<String, dynamic>>? profileRef; final List<Address> addresses; // 嵌套对象数组 final List<String> hobbies; // 基础类型数组 final List<int> scores; User({ required this.id, required this.name, required this.age, required this.isActive, required this.createdAt, required this.location, this.profileRef, required this.addresses, required this.hobbies, required this.scores, }); // fromJson:处理LinkedMap数组转换 factory User.fromJson(Map<String, dynamic> json) { return User( id: json['id'] as String, name: json['name'] as String, age: json['age'] as int, isActive: json['isActive'] as bool, createdAt: json['createdAt'] as Timestamp, location: json['location'] as GeoPoint, profileRef: json['profileRef'] as DocumentReference<Map<String, dynamic>>?, // 嵌套对象数组:遍历转成Address实例 addresses: (json['addresses'] as List) .map((item) => Address.fromJson(item as Map<String, dynamic>)) .toList(), // 基础类型数组:直接强转 hobbies: (json['hobbies'] as List).cast<String>(), scores: (json['scores'] as List).cast<int>(), ); } // toJson:转换为Firestore可识别格式 Map<String, dynamic> toJson() { return { 'id': id, 'name': name, 'age': age, 'isActive': isActive, 'createdAt': createdAt, 'location': location, 'profileRef': profileRef, // 对象列表转Map列表 'addresses': addresses.map((addr) => addr.toJson()).toList(), 'hobbies': hobbies, 'scores': scores, }; } }
2. 搭配withConverter使用
在集合/文档引用中绑定Converter,实现自动读写转换:
// 获取带Converter的集合引用 final CollectionReference<User> usersCollection = FirebaseFirestore.instance .collection('users') .withConverter<User>( fromFirestore: (snapshot, _) => User.fromJson(snapshot.data()!), toFirestore: (user, _) => user.toJson(), ); // 示例:添加用户 Future<void> addUser(User user) async { await usersCollection.add(user); } // 示例:获取单个用户 Future<User?> getUser(String userId) async { final docSnapshot = await usersCollection.doc(userId).get(); return docSnapshot.data(); } // 示例:监听用户列表 Stream<List<User>> getUsersStream() { return usersCollection.snapshots().map((snapshot) { return snapshot.docs.map((doc) => doc.data()).toList(); }); }
关键注意事项
- 嵌套对象数组:必须遍历每个
LinkedMap,调用对应数据类的fromJson,不能直接强转。 - 基础类型数组:直接用
cast<T>()即可完成转换。 - Firestore特殊类型(Timestamp、GeoPoint、DocumentReference):可直接在
fromJson/toJson中传递,Firestore会自动处理序列化。 - 空值处理:若数组可能为
null,需添加空判断,例如:addresses: (json['addresses'] as List?) ?.map((item) => Address.fromJson(item as Map<String, dynamic>)) .toList() ?? [],
内容的提问来源于stack exchange,提问作者cmjordan
相关产品推荐
相关产品推荐

