Flutter中用Freezed+Firebase处理GeoPoint序列化构建报错求助
解决Freezed结合Firebase GeoPoint的JSON序列化问题
针对你用Freezed+Firebase处理GeoPoint时遇到的构建错误,这里提供一套可行的解决方案:
1. 编写GeoPoint专用JsonConverter
创建一个转换器类,负责GeoPoint与JSON格式的双向转换,适配Firestore和本地测试JSON的结构:
import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:json_annotation/json_annotation.dart'; class GeoPointConverter implements JsonConverter<GeoPoint, Map<String, dynamic>> { const GeoPointConverter(); @override GeoPoint fromJson(Map<String, dynamic> json) { return GeoPoint( (json['latitude'] as num).toDouble(), (json['longitude'] as num).toDouble(), ); } @override Map<String, dynamic> toJson(GeoPoint object) { return { 'latitude': object.latitude, 'longitude': object.longitude, }; } }
2. 在Freezed类中应用转换器
修改你的Place类,通过@JsonSerializable注解全局应用转换器,确保Freezed生成的代码能正确处理GeoPoint类型:
import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; part 'place.freezed.dart'; part 'place.g.dart'; @Freezed() @JsonSerializable(converters: [GeoPointConverter()]) class Place with _$Place { const factory Place({ required String id, required String name, required GeoPoint location, }) = _Place; factory Place.fromJson(Map<String, dynamic> json) => _$PlaceFromJson(json); }
如果只需要给location字段单独配置转换器,也可以直接在字段上标注:
const factory Place({ required String id, required String name, @GeoPointConverter() required GeoPoint location, }) = _Place;
3. 验证测试JSON结构
确保places.json中的location字段格式与转换器匹配,示例结构:
[ { "id": "1", "name": "测试地点", "location": { "latitude": 31.2304, "longitude": 121.4737 } } ]
4. 重新执行构建命令
清理旧的生成文件并重新构建,避免缓存冲突:
flutter pub run build_runner build --delete-conflicting-outputs
关键说明
之前尝试的@JsonKey自定义方法容易和Freezed的代码生成逻辑冲突,而JsonConverter是更适配Freezed+json_serializable组合的方案——它会被Freezed识别并自动注入到序列化/反序列化流程中,同时兼容Firestore的GeoPoint存储格式:
- 写入Firestore时,直接将
Place对象传入setData,Firestore会自动识别GeoPoint类型 - 读取Firestore数据时,用
Place.fromJson(doc.data()!)即可完成反序列化
内容的提问来源于stack exchange,提问作者Chris Harri
相关产品推荐
相关产品推荐

