同一接口返回不同JSON,如何转换为Dart模型?
解决同一API返回不同JSON结构的Dart模型转换问题
针对同一接口返回不同JSON结构的情况,给你几个实用的处理方案:
方案1:定义统一模型,通过字段映射兼容不同结构
创建一个包含所有可能字段的模型类,利用json_serializable的@JsonKey注解,把不同JSON里的同义字段映射到模型的同一个属性上。这样不管返回哪种结构,都能统一解析成同一个模型对象。
示例代码:
import 'package:json_annotation/json_annotation.dart'; part 'unified_model.g.dart'; @JsonSerializable() class UnifiedContent { final String title; // 同时兼容"thumbnail"和"thumb"字段 @JsonKey(name: 'thumbnail', defaultValue: '') final String thumbnail; @JsonKey(name: 'thumb', defaultValue: '') String get thumb => thumbnail.isNotEmpty ? thumbnail : ''; // 同时兼容"url"和"video_url"字段 @JsonKey(name: 'url', defaultValue: '') final String url; @JsonKey(name: 'video_url', defaultValue: '') String get videoUrl => url.isNotEmpty ? url : ''; // 同时兼容"urlList"和"videoUrlList"字段 @JsonKey(name: 'urlList', defaultValue: []) final List<String> urlList; @JsonKey(name: 'videoUrlList', defaultValue: []) List<String> get videoUrlList => urlList.isNotEmpty ? urlList : []; UnifiedContent({ required this.title, required this.thumbnail, required this.url, required this.urlList, }); factory UnifiedContent.fromJson(Map<String, dynamic> json) => _$UnifiedContentFromJson(json); Map<String, dynamic> toJson() => _$UnifiedContentToJson(this); }
这种方式的好处是上层代码不用区分响应类型,直接使用统一模型的getter获取对应数据即可。
方案2:先判断响应类型,再分别解析成对应模型
如果两种结构差异很大,没必要强行统一,可以先把响应转成Map<String, dynamic>,通过判断特定字段的存在来区分类型,再分别实例化不同的模型类。
首先定义两个模型类:
// 对应JSON响应1的模型 class ContentType1 { final String title; final String thumbnail; final String url; final List<String> urlList; ContentType1({ required this.title, required this.thumbnail, required this.url, required this.urlList, }); factory ContentType1.fromJson(Map<String, dynamic> json) { return ContentType1( title: json['title'], thumbnail: json['thumbnail'], url: json['url'], urlList: List<String>.from(json['urlList']), ); } } // 对应JSON响应2的模型 class ContentType2 { final String title; final String thumb; final String videoUrl; final List<String> videoUrlList; ContentType2({ required this.title, required this.thumb, required this.videoUrl, required this.videoUrlList, }); factory ContentType2.fromJson(Map<String, dynamic> json) { return ContentType2( title: json['title'], thumb: json['thumb'], videoUrl: json['video_url'], videoUrlList: List<String>.from(json['videoUrlList']), ); } }
然后在解析的时候做判断:
dynamic parseResponse(Map<String, dynamic> json) { if (json.containsKey('thumbnail')) { return ContentType1.fromJson(json); } else if (json.containsKey('thumb')) { return ContentType2.fromJson(json); } throw Exception('未知的响应类型'); }
上层代码拿到解析结果后,可以通过is关键字判断类型,再做对应处理:
var responseData = parseResponse(jsonMap); if (responseData is ContentType1) { // 处理类型1的数据 } else if (responseData is ContentType2) { // 处理类型2的数据 }
方案3:使用动态类型(不推荐)
如果只是临时快速处理,可以直接用Map<String, dynamic>或者dynamic类型来存取数据,但这种方式会丢失类型检查,代码可读性和可维护性差,不建议在正式项目中使用。
内容的提问来源于stack exchange,提问作者shakti goyal
相关产品推荐
相关产品推荐

