具有 json_serializable 的复杂模型 - List<objects> 未转换为地图
Posted
技术标签:
【中文标题】具有 json_serializable 的复杂模型 - List<objects> 未转换为地图【英文标题】:Complex models with json_serializable - List<objects> not converting to map 【发布时间】:2020-06-21 01:21:33 【问题描述】:更新 我已经构建了一个小示例,并将所有代码添加到这篇文章中。我必须相信对此有答案/解释,并希望有人可以教育我我所缺少的东西。对象类型的类字段没有被转换,我不明白为什么。
这是我正在使用的模型类。
import 'package:json_annotation/json_annotation.dart';
part 'parent.g.dart';
@JsonSerializable()
class Parent
int id;
final String name;
final int age;
List<Child> children;
Job job;
Parent(this.name, this.age, this.children, this.job);
factory Parent.fromJson(Map<String, dynamic> json) => _$ParentFromJson(json);
Map<String, dynamic> toJson() => _$ParentToJson(this);
@JsonSerializable()
class Child
int id;
final String name;
final int age;
Child(this.name, this.age);
factory Child.fromJson(Map<String, dynamic> json) => _$ChildFromJson(json);
Map<String, dynamic> toJson() => _$ChildToJson(this);
@JsonSerializable()
class Job
int id;
String title;
Job(this.title);
factory Job.fromJson(Map<String, dynamic> json) => _$JobFromJson(json);
Map<String, dynamic> toJson() => _$JobToJson(this);
这是为这些类生成的 .g 文件
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'parent.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
Parent _$ParentFromJson(Map<String, dynamic> json)
return Parent(
name: json['name'] as String,
age: json['age'] as int,
children: (json['children'] as List)
?.map(
(e) => e == null ? null : Child.fromJson(e as Map<String, dynamic>))
?.toList(),
job: json['job'] == null
? null
: Job.fromJson(json['job'] as Map<String, dynamic>),
)..id = json['id'] as int;
Map<String, dynamic> _$ParentToJson(Parent instance) => <String, dynamic>
'id': instance.id,
'name': instance.name,
'age': instance.age,
'children': instance.children,
'job': instance.job,
;
Child _$ChildFromJson(Map<String, dynamic> json)
return Child(
name: json['name'] as String,
age: json['age'] as int,
)..id = json['id'] as int;
Map<String, dynamic> _$ChildToJson(Child instance) => <String, dynamic>
'id': instance.id,
'name': instance.name,
'age': instance.age,
;
Job _$JobFromJson(Map<String, dynamic> json)
return Job(
title: json['title'] as String,
)..id = json['id'] as int;
Map<String, dynamic> _$JobToJson(Job instance) => <String, dynamic>
'id': instance.id,
'title': instance.title,
;
这里是父类的DAO类
import 'package:sembast/sembast.dart';
import 'package:json_serial_test/services/app_database.dart';
import 'package:json_serial_test/models/parent.dart';
class ParentDao
static const String PARENT_STORE_NAME = 'parents';
// A Store with int keys and Map<String, dynamic> values.
// This Store acts like a persistent map, values of which are Parent objects converted to Map
final _parentStore = intMapStoreFactory.store(PARENT_STORE_NAME);
// Private getter to shorten the amount of code needed to get the
// singleton instance of an opened database.
Future<Database> get _db async => await AppDatabase.instance.database;
Future insert(Parent parent) async
await _parentStore.add(await _db, parent.toJson());
Future update(Parent parent) async
// For filtering by key (ID), RegEx, greater than, and many other criteria,
// we use a Finder.
final finder = Finder(filter: Filter.byKey(parent.id));
await _parentStore.update(
await _db,
parent.toJson(),
finder: finder,
);
Future deleteAll() async
await _parentStore.delete(await _db);
Future delete(Parent parent) async
final finder = Finder(filter: Filter.byKey(parent.id));
await _parentStore.delete(
await _db,
finder: finder,
);
Future<List<Parent>> getAllSortedByName() async
// Finder object can also sort data.
final finder = Finder(sortOrders: [
SortOrder('name'),
]);
final recordSnapshots = await _parentStore.find(
await _db,
finder: finder,
);
// Making a List<Parent> out of List<RecordSnapshot>
return recordSnapshots.map((snapshot)
final parent = Parent.fromJson(snapshot.value);
// An ID is a key of a record from the database.
parent.id = snapshot.key;
return parent;
).toList();
这是我的测试
// Setup
final k1 = Child(name: 'Billy', age: 10);
final k2 = Child(name: 'Jannet', age: 9);
final job = Job(title: 'Cook');
final List<Child> kids = [k1, k2];
final dad = Parent(name: 'Dave', age: 52, job: job, children: kids);
await pDao.insert(dad);
List<Parent> dadsInDb = await pDao.getAllSortedByName();
print('Dads from DB: $dadsInDb.toString()');
在尝试将 Parent 插入到我的 sembast 数据库中时,出现此错误。
E/flutter (12986): [ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: Invalid argument(s): value Instance of 'Child' unsupported type Child E/flutter (12986): #0 cloneValue (package:sembast/src/utils.dart:191:3) E/flutter (12986): #1 cloneValue.<anonymous closure> (package:sembast/src/utils.dart:177:33) E/flutter (12986): #2 MappedListIterable.elementAt (dart:_internal/iterable.dart:417:29) E/flutter (12986): #3 ListIterable.toList (dart:_internal/iterable.dart:221:19) E/flutter (12986): #4 cloneValue (package:sembast/src/utils.dart:177:52) E/flutter (12986): #5 cloneValue.<anonymous closure> (package:sembast/src/utils.dart:174:49) E/flutter (12986): #6 MapMixin.map (dart:collection/maps.dart:165:28) E/flutter (12986): #7 cloneValue (package:sembast/src/utils.dart:173:18) E/flutter (12986):
#8 SembastStore.txnPutSync (package:sembast/src/store_impl.dart:133:15) E/flutter (12986): #9 SembastStore.txnAdd (package:sembast/src/store_impl.dart:117:11) E/flutter (12986): <asynchronous suspension> E/flutter (12986): #10 StoreRefMixin.add.<anonymous closure> (package:sembast/src/store_ref_impl.dart:75:12) E/flutter (12986): #11 SembastDatabase.inTransaction.<anonymous closure> (package:sembast/src/database_impl.dart:1238:34) E/flutter (12986):
#12 SembastDatabase.transaction.<anonymous closure>.<anonymous closure> (package:sembast/src/database_impl.dart:1090:59) E/flutter (12986): #13 new Future.sync (dart:async/future.dart:224:31) E/flutter (12986): #14 SembastDatabase.transaction.<anonymous closure> (package:sembast/src/database_impl.dart:1090:26) E/flutter (12986): #15 BasicLock.synchronized (package:synchronized/src/basic_lock.dart:32:26) E/flutter (12986):
#16 SembastDatabase.transaction (package:sembast/src/database_impl.dart:1073:38) E/flutter (12986):
#17 SembastDatabase.inTransaction (package:sembast/src/database_impl.dart:1238:7) E/flutter (12986): #18 StoreRefMixin.add (package:sembast/src/store_ref_impl.dart:72:25) E/flutter (12986): #19 ParentDao.insert (package:json_serial_test/data/parent_dao.dart:17:24) E/flutter (12986): <asynchronous suspension> E/flutter (12986): #20
_MyHomePageState.build.<anonymous closure> (package:json_serial_test/main.dart:120:22) E/flutter (12986): #21
_InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:706:14) E/flutter (12986):
#22 _InkResponseState.build.<anonymous closure> (package:flutter/src/material/ink_well.dart:789:36) E/flutter (12986):
#23 GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:182:24) E/flutter (12986): #24 TapGestureRecognizer.handleTapUp (package:flutter/src/gestures/tap.dart:486:11) E/flutter (12986): #25 BaseTapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:264:5) E/flutter (12986): #26 BaseTapGestureRecognizer.acceptGesture (package:flutter/src/gestures/tap.dart:236:7) E/flutter (12986): #27 GestureArenaManager.sweep (package:flutter/src/gestures/arena.dart:156:27) E/flutter (12986):
#28 GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:222:20) E/flutter (12986):
#29 GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:198:22) E/flutter (12986):
#30 GestureBinding._handlePointerEvent (package:flutter/src/gestures/binding.dart:156:7) E/flutter (12986):
#31 GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:102:7) E/flutter (12986):
#32 GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:86:7) E/flutter (12986):
#33 _rootRunUnary (dart:async/zone.dart:1138:13) E/flutter (12986): #34 _CustomZone.runUnary (dart:async/zone.dart:1031:19) E/flutter (12986): #35 _CustomZone.runUnaryGuarded (dart:async/zone.dart:933:7) E/flutter (12986): #36 _invoke1 (dart:ui/hooks.dart:273:10) E/flutter (12986): #37
_dispatchPointerDataPacket (dart:ui/hooks.dart:182:5) E/flutter (12986):
如果有人可以帮助我展示我错过了什么,做错了什么,我将不胜感激。
原帖
==============
json_serializable
应该将所有类转换为 JSON,还是我遇到了限制?
我决定尝试解决我自己造成的一系列问题,方法是使用 json_serializable
创建使用 NoSQL DB
所需的 toJson 和 fromJson 方法。
如果我创建一个包含 List<Ojb>
字段的类,生成的代码似乎会为类的每个字段生成 JSON,但对于列表中的对象却没有这样做。
简单示例
class Parent
final int age;
final String name;
List<Child> children;
Parent(this.age, this.name, this.children);
class Child
final int age;
final String name;
Child(this.age, this.name);
当我使用 json_serializable 时,它似乎工作得很好,我得到了上述类的 toJson 和 fromJson 方法。乍一看,一切看起来都很完美。
当我尝试将父级(包含子级)插入我的 NoSQL 数据库时,插入未能说明不支持该类型(引用子级对象) - True 语句,对此没有任何问题。
当我通过调试器单步执行此操作时,这就是我所看到的。
Parent
转换为地图
年龄以其价值显示为关键
名称显示为带有其值的键
到目前为止,我可以看到一切都是地图[..而且一切看起来都很棒
然后我们得到子对象的列表。
这部分没有转换成映射,但仍然作为子对象的列表存在,因此插入失败。
两个类都有jsonSerializable
注解
两个类都在生成预期的代码(部分),类
只要我不尝试在我的课程中使用List<myObject>
,一切都会完美运行。
使用像 json_serializable 这样的包的全部原因是依赖于自动生成的代码,而不必自己构建它。我不想手动更新自动生成的代码来解决这个问题,这就是我没有粘贴代码的原因。如果这就是答案,那我就另辟蹊径了。
我的问题是...是否有一些我遗漏或可能做错的配置允许类中的所有项目转换为 map/json,即使类的字段不只是简单的 int 和 string 类型。我希望我可以拥有一个包含基元的类,以及对象、对象列表等,并且所有内容都应该正确生成,或者没有?
【问题讨论】:
你必须在build.yaml中生成toJson才能进行json序列化 嗨,Ayush,您能进一步解释一下您的意思吗?我确实意识到我可以使用构建配置 pubspec.yaml 文件来配置可序列化,但这对文件的生成方式有何影响? 您进行了大量编辑。你能确认它不会改变问题吗? IE。您的编辑不会使现有答案无效?我问是因为编辑的大小以及您已经接受了答案的事实...... 【参考方案1】:经过多次试验和重建,我已经解决了这个问题,现在一切似乎都可以在我的 Sembast DB 上使用 json_serializable 用于我的模型类。可能还有其他因素促成了我的成功,但我认为主要区别在于将以下参数添加到 Parent 类的 JSONSerializable 注释中。
explicitToJson: true
这是代码,如果它可以帮助其他人。
你可以在这里找到完整的解释https://flutter.dev/docs/development/data-and-backend/json
@JsonSerializable(explicitToJson: true)
class Parent
int id;
final String name;
final int age;
List<Child> children;
Job job;
Parent(this.name, this.age, this.children, this.job);
factory Parent.fromJson(Map<String, dynamic> json) => _$ParentFromJson(json);
Map<String, dynamic> toJson() => _$ParentToJson(this);
【讨论】:
对于使用 freezed 遇到此问题的任何人 - 请参阅 github.com/rrousselGit/freezed/issues/86#issuecomment-593936459以上是关于具有 json_serializable 的复杂模型 - List<objects> 未转换为地图的主要内容,如果未能解决你的问题,请参考以下文章
在 nullsafety 之后使用带有 json_serializable 的 firestore
颤振:json_serializable 1 => true,0 => false
Flutter:将 50 多个模型类转换为支持 json_serializable 的快速方法