使用built_value反序列化JSON时遇类型转换错误求助
我在Flutter项目里用built_value定义了对应JSON结构的PODO类,执行flutter packages pub run build_runner build生成代码后,HTTP请求反序列化时碰到了这个错误:
Deserializing '{status: 1, msg: Success, data: {lastIndex: 50, studentData: [{student_id: 62...' to 'StudentModel' failed due to: type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'Iterable
' in type cast
用普通PODO类的时候完全没问题,想问下怎么解决?
我的代码片段
PODO类代码
library student_model; import 'dart:convert'; import 'package:built_collection/built_collection.dart'; import 'package:built_value/built_value.dart'; import 'package:built_value/serializer.dart'; part 'student_model.g.dart'; abstract class StudentModel implements Built<StudentModel, StudentModelBuilder> { StudentModel._(); factory StudentModel([updates(StudentModelBuilder b)]) = _$StudentModel; @BuiltValueField(wireName: 'status') int get status; @BuiltValueField(wireName: 'msg') String get msg; @BuiltValueField(wireName: 'data') StudentModelData get data; static Serializer<StudentModel> get serializer => _$studentModelSerializer; } abstract class StudentModelData implements Built<StudentModelData, StudentModelDataBuilder> { StudentModelData._(); factory StudentModelData([updates(StudentModelDataBuilder b)]) = _$StudentModelData; @BuiltValueField(wireName: 'lastIndex') int get lastIndex; @BuiltValueField(wireName: 'studentData') BuiltList<StudentData> get studentData; static Serializer<StudentModelData> get serializer => _$studentModelDataSerializer; } abstract class StudentData implements Built<StudentData,StudentDataBuilder> { StudentData._(); factory StudentData([updates(StudentDataBuilder b)]) = _$StudentData; @BuiltValueField(wireName: 'student_id') String get studentId; @BuiltValueField(wireName: 'stud_name') String get studentName; @BuiltValueField(wireName: 'stud_profilepic') String get studentProfilePicture; @BuiltValueField(wireName: 'student_email') String get studentEmail; @BuiltValueField(wireName: 'course_name') String get courseName; @BuiltValueField(wireName: 'class_code') String get classCode; @BuiltValueField(wireName: 'minAvg') int get minAverage; @BuiltValueField(wireName: 'avg') int get average; static Serializer<StudentData> get serializer => _$studentDataSerializer; }
序列化类代码
library serializers; import 'package:built_value/serializer.dart'; import 'package:built_collection/built_collection.dart'; import 'package:built_value/standard_json_plugin.dart'; import 'package:infinite_list/models/student_model.dart'; part 'serializers.g.dart'; @SerializersFor(const [StudentModel,]) Serializers serializers = _$serializers; Serializers standardSerializers = (serializers.toBuilder()..addPlugin(StandardJsonPlugin())).build();
HTTP请求代码
Future<StudentModel> fetchStudents(String disciplineId, String schoolId, String year_id, String lastIndex) async { final response = await http.post(GET_STUDENTS, body: { "schoolId": schoolId, "year_id": year_id, }); StudentModel studentModel = serializers.deserializeWith(StudentModel.serializer, json.decode(response.body)); return studentModel; }
问题原因&解决方案
核心问题
你只在@SerializersFor注解里添加了StudentModel,但嵌套的StudentModelData和StudentData的序列化器没被注册到序列化器集合中。built_value在解析data字段时,找不到对应的类型处理逻辑,错误地把它当成了可迭代类型(Iterable)来转换,于是抛出了类型不匹配的异常。
修复步骤
1. 更新序列化类,注册所有模型
把所有相关的模型类都添加到@SerializersFor的列表里:
library serializers; import 'package:built_value/serializer.dart'; import 'package:built_collection/built_collection.dart'; import 'package:built_value/standard_json_plugin.dart'; import 'package:infinite_list/models/student_model.dart'; part 'serializers.g.dart'; // 加入所有需要序列化的模型类 @SerializersFor(const [StudentModel, StudentModelData, StudentData]) Serializers serializers = _$serializers; Serializers standardSerializers = (serializers.toBuilder()..addPlugin(StandardJsonPlugin())).build();
2. 使用带插件的序列化器反序列化
你已经添加了StandardJsonPlugin来处理普通JSON格式,但之前的代码用的是原始的serializers,应该换成standardSerializers:
Future<StudentModel> fetchStudents(String disciplineId, String schoolId, String year_id, String lastIndex) async { final response = await http.post(GET_STUDENTS, body: { "schoolId": schoolId, "year_id": year_id, }); // 改用standardSerializers StudentModel studentModel = standardSerializers.deserializeWith(StudentModel.serializer, json.decode(response.body)); return studentModel; }
3. 重新生成代码
修改完成后,执行命令重新生成序列化相关代码:
flutter packages pub run build_runner build --delete-conflicting-outputs
这样处理后,序列化器就能正确识别所有嵌套的模型类型,完美完成JSON到built_value对象的转换了。
内容的提问来源于stack exchange,提问作者BraveEvidence

