Flutter嵌套JSON序列化失效?已设置explicitToJson: true仍无效
Flutter嵌套JSON解析测试失败问题解决
我是Flutter新手,正在开发一个从本地模拟数据库拉取嵌套JSON结构数据的小型API。不管怎么操作,都无法输出实际JSON数据,得到的总是“Instance of 'Class'”。以下是相关代码和测试报错情况:
模型代码
Exercise模型
import 'package:json_annotation/json_annotation.dart'; import 'package:workout_card_api/src/models/sets.dart'; part 'exercise.g.dart'; @JsonSerializable(explicitToJson: true) class Exercise { Exercise({ required this.exerciseId, required this.exerciseName, required this.exerciseType, required this.setList, }); int exerciseId; String exerciseName; String exerciseType; List<Sets> setList; factory Exercise.fromJson(Map<String, dynamic> json) => _$ExerciseFromJson(json); Map<String, dynamic> toJson() => _$ExerciseToJson(this); }
Sets模型
import 'package:json_annotation/json_annotation.dart'; part 'sets.g.dart'; @JsonSerializable() class Sets { Sets({required this.setId, required this.weightKg, required this.reps}); int setId; int weightKg; int reps; factory Sets.fromJson(Map<String, dynamic> json) => _$SetsFromJson(json); Map<String, dynamic> toJson() => _$SetsToJson(this); }
测试代码
void main() { group('Sets', () { late Map<String, dynamic> json; setUp(() { json = {'setId': 1, 'weightKg': 30, 'reps': 15}; }); test('set object correct properties', () { final setData = Sets.fromJson(json); expect(setData.setId, 1); expect(setData.weightKg, 30); expect(setData.reps, 15); }); }); group('Exercise', () { late Map<String, dynamic> json; setUp(() { json = { 'exerciseId': 2, 'exerciseName': 'Bicep Curl', 'exerciseType': 'Arms', 'setList': [ {'setId': 1, 'weightKg': 30, 'reps': 15}, {'setId': 2, 'weightKg': 30, 'reps': 14}, {'setId': 3, 'weightKg': 30, 'reps': 12} ] }; }); test('exercise object correct properties', () { final exerciseData = Exercise.fromJson(json); expect(exerciseData.exerciseId, 2); expect(exerciseData.exerciseName, 'Bicep Curl'); expect(exerciseData.exerciseType, 'Arms'); expect(exerciseData.setList, [ {'setId': 1, 'weightKg': 30, 'reps': 15}, {'setId': 2, 'weightKg': 30, 'reps': 14}, {'setId': 3, 'weightKg': 30, 'reps': 12} ]); }); }); }
测试错误信息
Expected: [ {'setId': 1, 'weightKg': 30, 'reps': 15}, {'setId': 2, 'weightKg': 30, 'reps': 14}, {'setId': 3, 'weightKg': 30, 'reps': 12} ] Actual: [Instance of 'Sets', Instance of 'Sets', Instance of 'Sets'] Which: at location [0] is <Instance of 'Sets'> which expected a map
我试过把类型从Map<String, dynamic>改成Map<String, Object>,也创建过单独的build.yaml文件,但都没解决问题!
解决方案
问题根源
测试用例里你期望setList是Map数组,但Exercise.fromJson解析后,setList实际是Sets对象数组,类型不匹配导致测试失败。而直接打印对象显示“Instance of 'Sets'”,是因为Dart默认的对象toString()方法只会输出类实例标识。
具体解决步骤
修正测试断言逻辑
不要直接对比对象数组和Map数组,而是验证每个Sets对象的属性,或者把对象转成Map后再对比:- 方式一:逐个验证属性
test('exercise object correct properties', () { final exerciseData = Exercise.fromJson(json); expect(exerciseData.exerciseId, 2); expect(exerciseData.exerciseName, 'Bicep Curl'); expect(exerciseData.exerciseType, 'Arms'); // 验证setList的长度和每个对象的属性 expect(exerciseData.setList.length, 3); expect(exerciseData.setList[0].setId, 1); expect(exerciseData.setList[0].weightKg, 30); expect(exerciseData.setList[0].reps, 15); expect(exerciseData.setList[1].setId, 2); expect(exerciseData.setList[1].weightKg, 30); expect(exerciseData.setList[1].reps, 14); expect(exerciseData.setList[2].setId, 3); expect(exerciseData.setList[2].weightKg, 30); expect(exerciseData.setList[2].reps, 12); }); - 方式二:将对象转成Map数组后对比
test('exercise object correct properties', () { final exerciseData = Exercise.fromJson(json); expect(exerciseData.exerciseId, 2); expect(exerciseData.exerciseName, 'Bicep Curl'); expect(exerciseData.exerciseType, 'Arms'); // 调用toJson()把每个Sets对象转成Map,再对比 expect( exerciseData.setList.map((set) => set.toJson()).toList(), [ {'setId': 1, 'weightKg': 30, 'reps': 15}, {'setId': 2, 'weightKg': 30, 'reps': 14}, {'setId': 3, 'weightKg': 30, 'reps': 12} ] ); });
- 方式一:逐个验证属性
解决对象打印显示“Instance of 'Class'”的问题
- 重写类的
toString()方法,自定义输出格式:// 在Sets类中添加 @override String toString() { return 'Sets(setId: $setId, weightKg: $weightKg, reps: $reps)'; } // 在Exercise类中添加 @override String toString() { return 'Exercise(exerciseId: $exerciseId, exerciseName: $exerciseName, exerciseType: $exerciseType, setList: $setList)'; } - 或者直接输出JSON格式字符串:
import 'dart:convert'; // 打印Exercise对象的JSON字符串 print(jsonEncode(exerciseData.toJson()));
- 重写类的
确保代码生成正确
重新运行代码生成命令,确保嵌套JSON解析的.g.dart文件正确生成:flutter pub run build_runner build
内容的提问来源于stack exchange,提问作者Nova From OUTER SPACE
相关产品推荐
相关产品推荐

