使用Freezed包构建Dart模型解析JSON时遇类型转换错误求助
问题:调用
searchImageBasedCategory函数触发类型转换错误 报错信息:type 'Null' is not a subtype of type 'String' in type cast
原因分析
- 文件扩展名处理存在Null风险:当传入的文件无扩展名时,
p.extension(file.path)返回空字符串,split('.')后仅得到单元素列表,此时访问finalExtension[1]会返回Null,而MediaType的第二个参数要求非Null的String类型,直接触发类型转换错误。 - 模型字段与接口数据类型不匹配:接口返回的
prob和area是浮点型(如0.95788...),但BoundBoxItem模型中定义为int?,后续会引发额外类型错误。 - 必填String字段可能为Null:若实际接口响应中
category或gender字段返回Null,而模型标记这两个字段为required String,会触发Null转String的类型错误(即使示例JSON正常,实际场景可能存在异常)。
解决方案
1. 修复文件扩展名处理逻辑
添加空值判断,确保获取有效扩展名或设置默认值:
static Future<SearchResponse?> searchImageBasedCategory( File file, {requiresToken = true}) async { try { String fileExtension = p.extension(file.path); String ext = 'jpg'; // 设置默认扩展名 if (fileExtension.isNotEmpty) { List<String> finalExtension = fileExtension.split('.'); if (finalExtension.length > 1) { ext = finalExtension[1]; } } var formData = FormData.fromMap({ 'searchImage': await MultipartFile.fromFile( file.path, contentType: MediaType("image", ext), ), }); var res = await NetworkCommon.dio.post( EndPoints.imageBasedSearch, options: Options( headers: {'requires_token': true}, ), data: formData, ); var response = SearchResponse.fromJson(res.data); return response; } catch (error, stackTrace) { print('请求错误详情: $error'); print('堆栈信息: $stackTrace'); return null; } }
2. 修正模型字段类型
将BoundBoxItem中的prob和area改为double?,匹配接口返回的浮点型数据:
@freezed class BoundBoxItem with _$BoundBoxItem { factory BoundBoxItem({ required String category, double? prob, double? area, required List<int> bound_box, List<int>? expand_by_bound_box, required String gender }) = _BoundBoxItem; factory BoundBoxItem.fromJson(Map<String, dynamic> json) => _$BoundBoxItemFromJson(json); }
3. 处理必填字段为Null的情况
若接口可能返回Null的必填字段,可选择两种方式:
- 与后端协商,确保
category和gender始终返回非Null值; - 修改模型为可空类型并设置默认值:
@freezed class BoundBoxItem with _$BoundBoxItem { factory BoundBoxItem({ @Default("unknown") String category, double? prob, double? area, required List<int> bound_box, List<int>? expand_by_bound_box, @Default("unknown") String gender }) = _BoundBoxItem; factory BoundBoxItem.fromJson(Map<String, dynamic> json) => _$BoundBoxItemFromJson(json); }
内容的提问来源于stack exchange,提问作者hangMan
相关产品推荐
相关产品推荐

