Flutter开发中如何将Firebase实时数据库返回的动态键作为ID赋值
解决方案
你需要调整实体类的序列化方法和请求解析逻辑,两步即可完成:
1. 修改Products类的fromJson工厂方法
因为产品ID存在于Map的键位置,不存在于属性Map内部,所以我们新增一个id参数直接传入:
class Products { final String id; final String title; final String description; final double price; final String imageUrl; Products({ required this.id, required this.title, required this.description, required this.price, required this.imageUrl }); // 调整工厂方法,接收外部传入的id factory Products.fromJson(String id, Map<String, dynamic> map) { return Products( id: id, title: map['title'] as String, description: map['description'] as String, // 兼容int类型的price返回,避免类型转换报错 price: (map['price'] as num).toDouble(), imageUrl: map['imageUrl'] as String ); } }
2. 重写fetchAndSetProducts解析逻辑
原方法直接将整个响应传入反序列化方法是错误的,你需要先遍历响应中products节点的所有键值对,把动态字符串键作为ID传入反序列化方法:
Future<void> fetchAndSetProducts() async { final url = Uri.https('form-app-c5343-default-rtdb.firebaseio.com', '/products.json?auth=$token'); final response = await http.get(url, headers: { HttpHeaders.authorizationHeader : 'Basic $token' }); if(response.statusCode == 200) { final Map<String, dynamic> responseData = json.decode(response.body); final Map<String, dynamic> productsRawMap = responseData['products'] ?? {}; final Map<String, Products> loadedProducts = {}; // 遍历所有键值对,key就是你需要的产品ID productsRawMap.forEach((productId, productAttrs) { loadedProducts[productId] = Products.fromJson(productId, productAttrs); }); _items = loadedProducts; notifyListeners(); } else { throw Exception("Cannot Authenticate"); } }
注意事项
- 如果你请求的接口路径是
/products.json,Firebase Realtime Database默认会直接返回产品列表的键值对,不需要再取responseData['products'],可以根据你打印的实际响应结构调整取值逻辑 - 建议补充空值判断逻辑,避免部分字段缺失导致的应用崩溃
内容的提问来源于stack exchange,提问作者coolhack7
相关产品推荐
相关产品推荐

