Flutter中ObjectBox关联模型赋值及Json序列化问题排查
问题
将Json转Dart工具生成的模型类作为ObjectBox的@Entity实体类使用时,遇到以下问题:
- 无法正确配置与
Area、ShipmentAction的关联关系; - 配置关联后,
fromJson和toJson方法失效; - 批量存储
ShipmentDetail时,循环内对象的Area属性正常,但存储后查询列表中Area信息丢失。
核心需求:在ShipmentDetail类中正确配置与Area、ShipmentAction的关联,同时保证fromJson/toJson方法正常运行。
问题分析
关联配置错误:
ShipmentDetail中objshipmentActions声明错误,应为ToMany<ShipmentAction>()而非ToMany<ShipmentAction>;@Backlink参数错误,需指向ShipmentAction中关联ShipmentDetail的字段名shipmentDetails,而非实体类名;- 冗余字段:同时存在普通List类型的
shipmentActions和ObjectBox的ToMany类型字段,导致序列化逻辑混乱。
序列化方法问题:
fromJson未正确处理ShipmentAction的关联,应将解析后的对象添加到ObjectBox的ToMany字段,而非冗余List;toJson需基于ObjectBox的关联字段生成JSON,而非废弃的冗余字段。
批量存储问题:
- 存储
ShipmentDetail前未先持久化关联的Area实体,ObjectBox无法自动关联未存储的对象; - 属性拷贝不完整,未正确处理关联关系的持久化逻辑。
- 存储
修正后的完整实体类代码
ShipmentDetail 实体类
import 'package:objectbox/objectbox.dart'; import 'area.dart'; import 'shipment_action.dart'; import 'shipment_type.dart'; @Entity() class ShipmentDetail { @Id() int id = 0; late String barcode; late ShipmentType? shipmentType; late bool isSynced = false; late String startDeliveryTime = "00:00:00"; late String endDeliveryTime = "00:00:00"; late bool isChange = false; late String civilId; late String? latitude; late String? longitude; // 与Area的一对一关联 final area = ToOne<Area>(); // 与ShipmentAction的一对多反向关联,指向ShipmentAction中的shipmentDetails字段 @Backlink() final shipmentActions = ToMany<ShipmentAction>(); ShipmentDetail({ required this.barcode, this.shipmentType, this.isSynced = false, required this.civilId, this.latitude, this.longitude, }); // 空构造函数用于ObjectBox内部实例化 ShipmentDetail.empty(); ShipmentDetail.fromJson(Map<String, dynamic> json) { barcode = json['barcode']; civilId = json['civilId'] ?? ''; longitude = json['longitude'] ?? ''; latitude = json['latitude'] ?? ''; isSynced = json['isSynced'] ?? false; startDeliveryTime = json['startDeliveryTime'] ?? "00:00:00"; endDeliveryTime = json['endDeliveryTime'] ?? "00:00:00"; isChange = json['isChange'] ?? false; // 解析Area关联 if (json['area'] != null) { area.target = Area.fromJson(json['area']); } // 解析ShipmentType if (json['shipmentType'] != null) { shipmentType = ShipmentType.fromJson(json['shipmentType']); } // 解析ShipmentAction列表并建立双向关联 if (json['shipmentActions'] != null) { shipmentActions.clear(); json['shipmentActions'].forEach((v) { final action = ShipmentAction.fromJson(v); action.shipmentDetails.target = this; shipmentActions.add(action); }); } } Map<String, dynamic> toJson() { final Map<String, dynamic> data = {}; data['barcode'] = barcode; data['civilId'] = civilId; data['longitude'] = longitude; data['latitude'] = latitude; data['isSynced'] = isSynced; data['startDeliveryTime'] = startDeliveryTime; data['endDeliveryTime'] = endDeliveryTime; data['isChange'] = isChange; // 序列化Area关联 if (area.target != null) { data['area'] = area.target!.toJson(); } // 序列化ShipmentType if (shipmentType != null) { data['shipmentType'] = shipmentType!.toJson(); } // 序列化ShipmentAction列表 if (shipmentActions.isNotEmpty) { data['shipmentActions'] = shipmentActions.map((v) => v.toJson()).toList(); } return data; } }
Area 实体类
import 'package:objectbox/objectbox.dart'; @Entity() class Area { @Id() int id = 0; // ObjectBox要求Id为非空int,默认0表示未持久化 late String? description; late String? descriptionEn; late int? paciId; Area({ this.id = 0, required this.description, this.descriptionEn = "", required this.paciId, }); Area.fromJson(Map<String, dynamic> json) { id = json['id'] ?? 0; description = json['description'] ?? ''; descriptionEn = json['descriptionEn'] ?? ""; paciId = json['paciId'] ?? 0; } Map<String, dynamic> toJson() { final Map<String, dynamic> data = {}; data['id'] = id; data['description'] = description; data['descriptionEn'] = descriptionEn; data['paciId'] = paciId; return data; } }
ShipmentAction 实体类
import 'package:objectbox/objectbox.dart'; import 'shipment_detail.dart'; import 'action_type.dart'; @Entity() class ShipmentAction { @Id() int id = 0; late int? newBulkId; late String? description; late ActionType? actions; // 与ShipmentDetail的多对一关联 final shipmentDetails = ToOne<ShipmentDetail>(); ShipmentAction({ this.id = 0, required this.newBulkId, required this.description, this.actions, }); ShipmentAction.fromJson(Map<String, dynamic> json) { id = json['id'] ?? 0; newBulkId = json['newBulkId']; description = json['description'] ?? ''; if (json['actions'] != null) { actions = ActionType.fromJson(json['actions']); } } Map<String, dynamic> toJson() { final Map<String, dynamic> data = {}; data['id'] = id; data['newBulkId'] = newBulkId; data['description'] = description; if (actions != null) { data['actions'] = actions!.toJson(); } return data; } }
批量存储代码修正
import 'package:objectbox/objectbox.dart'; import 'shipment_detail.dart'; import 'area.dart'; class ShipmentDbService { late Box<ShipmentDetail> _storageShipment; late Box<Area> _areaBox; late Box<ShipmentAction> _actionBox; ShipmentDbService(Store store) { _storageShipment = store.box<ShipmentDetail>(); _areaBox = store.box<Area>(); _actionBox = store.box<ShipmentAction>(); } Result<List<ShipmentDetail>> addAll(List<ShipmentDetail> data) { try { for (var item in data) { // 1. 先持久化关联的Area(未持久化时) if (item.area.target != null) { final area = item.area.target!; if (area.id == 0) { area.id = _areaBox.put(area); } item.area.target = area; } // 2. 持久化关联的ShipmentAction列表 for (var action in item.shipmentActions) { if (action.id == 0) { action.id = _actionBox.put(action); } } // 3. 存储ShipmentDetail if (item.id == 0) { item.id = _storageShipment.put(item); } else { _storageShipment.put(item); } } final shipmentsLst = _storageShipment.getAll().toList(); return Result.success(shipmentsLst); } catch (e) { return Result.error(e.toString()); } } } // 自定义结果封装类 class Result<T> { final bool isSuccess; final T? data; final String? error; Result.success(this.data) : isSuccess = true, error = null; Result.error(this.error) : isSuccess = false, data = null; }
内容的提问来源于stack exchange,提问作者ABD
相关产品推荐
相关产品推荐

