如何在Flutter中正确存储Supabase双表查询结果至数据模型?
Flutter中正确转换Supabase多表查询结果为对象的解决方案
问题场景
使用Supabase查询questions表及其关联的categories表(主分类和子分类),API返回的response包含正确数据,但转换为自定义Question对象时失败,导致页面持续显示CircularProgressIndicator,调试时打印questions无输出。
核心问题
sub_category_id允许为null,对应的sub_category字段在返回结果中可能是null,直接通过json['sub_category']['category_name']访问会触发空指针异常,中断对象转换流程;另外fromJson方法的参数类型不够严谨,增加了潜在的类型风险。
解决步骤
- 修复空安全处理:对可能为null的关联字段使用
?.安全访问符,配合??空合并运算符设置默认值(或保留null),避免空指针。 - 严谨类型声明:将
fromJson的参数类型从Map<dynamic, dynamic>改为Map<String, dynamic>,符合Supabase返回数据的实际类型。 - 添加调试辅助方法:给
Question类添加toString()方法,方便调试时打印对象内容。 - 细化异常捕获:在对象转换环节单独捕获异常,定位具体出错的条目,避免整个请求失败。
修改后的代码示例
优化后的Question类
class Question { final int id; final String questionText; final String? questionId; final int mainCategoryId; final String mainCategoryName; final int? subCategoryId; final String? subCategoryName; Question({ required this.id, required this.questionText, this.questionId, required this.mainCategoryId, required this.mainCategoryName, this.subCategoryId, this.subCategoryName, }); // 优化后的fromJson方法,处理空安全和严谨类型 Question.fromJson(Map<String, dynamic> json) : id = json['id'] as int, questionText = json['question_text'] as String, questionId = json['question_id'] as String?, mainCategoryId = json['main_category_id'] as int, // 主分类不会为null,直接安全访问 mainCategoryName = (json['main_category'] as Map<String, dynamic>)['category_name'] as String, subCategoryId = json['sub_category_id'] as int?, // 子分类可能为null,使用判空处理 subCategoryName = json['sub_category'] != null ? (json['sub_category'] as Map<String, dynamic>)['category_name'] as String? : null; // 添加toString方便调试 @override String toString() { return 'Question(id: $id, questionText: $questionText, mainCategoryName: $mainCategoryName, subCategoryName: $subCategoryName)'; } }
优化后的QuestionRepository类
class QuestionRepository { final supabase = Supabase.instance.client; Future<List<Question>> getQuestions() async { try { final response = await supabase.from('questions').select( '*, main_category: main_category_id(*), sub_category: sub_category_id(*)', ); if (response.isNotEmpty) { final List<Question> questions = []; for (final data in response) { try { // 单独捕获每个条目转换的异常,方便定位问题 questions.add(Question.fromJson(data as Map<String, dynamic>)); } catch (e) { print('转换条目失败: $data, 错误: $e'); } } // 打印转换后的结果,验证是否成功 print(questions); return questions; } else { throw Exception('没有查询到问题数据'); } } catch (error) { throw Exception('获取问题失败: $error'); } } }
验证方法
- 运行代码后查看控制台打印的
questions列表,确认对象是否正确转换 - 若有转换失败的条目,控制台会输出具体的错误信息和对应的数据,便于针对性修复
内容的提问来源于stack exchange,提问作者Sheenergizer
相关产品推荐
相关产品推荐

