如何在Dart中创建模型类并解析服务器返回的嵌套JSON?
优先使用
json_annotation+json_serializable解析嵌套JSON 对于你提供的这种多层嵌套的JSON结构,强烈推荐使用json_annotation和json_serializable库,手动解析不仅容易因字段拼写、类型转换出错,后续维护成本也极高——一旦JSON结构变更,你需要逐一修改所有解析逻辑,效率极低。
一、库的使用步骤
1. 添加依赖
在pubspec.yaml中添加以下依赖:
dependencies: json_annotation: ^4.8.1 dev_dependencies: build_runner: ^2.4.4 json_serializable: ^6.7.0
执行dart pub get安装依赖。
2. 创建嵌套模型类
从最内层的结构开始定义类,逐层向外扩展:
import 'package:json_annotation/json_annotation.dart'; // 自动生成的代码会放在这个文件中 part 'user_models.g.dart'; // 最内层:收藏颜色 @JsonSerializable() class FavColors { final List<String> colors; FavColors({required this.colors}); factory FavColors.fromJson(Map<String, dynamic> json) => _$FavColorsFromJson(json); Map<String, dynamic> toJson() => _$FavColorsToJson(this); } // 照片信息 @JsonSerializable() class Photos { final String avatar; final FavColors favColors; Photos({required this.avatar, required this.favColors}); factory Photos.fromJson(Map<String, dynamic> json) => _$PhotosFromJson(json); Map<String, dynamic> toJson() => _$PhotosToJson(this); } // 状态信息 @JsonSerializable() class Status { final String text; Status({required this.text}); factory Status.fromJson(Map<String, dynamic> json) => _$StatusFromJson(json); Map<String, dynamic> toJson() => _$StatusToJson(this); } // 用户主体 @JsonSerializable() class User { final int id; final String name; final int age; final Status status; final Photos photos; User({ required this.id, required this.name, required this.age, required this.status, required this.photos, }); factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json); Map<String, dynamic> toJson() => _$UserToJson(this); } // 最外层响应结构 @JsonSerializable() class ApiResponse { final List<User> users; ApiResponse({required this.users}); factory ApiResponse.fromJson(Map<String, dynamic> json) => _$ApiResponseFromJson(json); Map<String, dynamic> toJson() => _$ApiResponseToJson(this); }
3. 生成解析代码
在终端执行以下命令,自动生成user_models.g.dart文件:
dart pub run build_runner build
4. 实际解析示例
拿到服务器返回的JSON字符串后,直接调用生成的fromJson方法解析:
import 'dart:convert'; import 'user_models.dart'; void main() { String jsonResponse = ''' {"api_data": { "users": [ { "id": 100, "name": "Jhon", "age": 34, "status": { "text": "Hello, World!" }, "photos": { "avatar": "https://", "favColors": { "colors": ["#FFFFFF", "#09927F"] } } } ] }} '''; Map<String, dynamic> jsonMap = jsonDecode(jsonResponse); ApiResponse response = ApiResponse.fromJson(jsonMap['api_data']); print(response.users.first.name); // 输出:Jhon print(response.users.first.status.text); // 输出:Hello, World! }
二、手动解析的适用场景
只有当JSON结构极其简单(比如只有几个平级字段)时,手动解析才值得考虑。以你的JSON为例,手动解析的代码会非常繁琐:
import 'dart:convert'; void manualParse() { String jsonResponse = '''...'''; // 同上JSON字符串 Map<String, dynamic> root = jsonDecode(jsonResponse); List<dynamic> usersJson = root['api_data']['users']; List<UserManual> users = []; for (var userJson in usersJson) { StatusManual status = StatusManual(text: userJson['status']['text']); FavColorsManual favColors = FavColorsManual(colors: List<String>.from(userJson['photos']['favColors']['colors'])); PhotosManual photos = PhotosManual(avatar: userJson['photos']['avatar'], favColors: favColors); UserManual user = UserManual( id: userJson['id'], name: userJson['name'], age: userJson['age'], status: status, photos: photos, ); users.add(user); } print(users.first.name); } // 手动解析对应的实体类 class UserManual { final int id; final String name; final int age; final StatusManual status; final PhotosManual photos; UserManual({required this.id, required this.name, required this.age, required this.status, required this.photos}); } class StatusManual {final String text; StatusManual({required this.text});} class PhotosManual {final String avatar; final FavColorsManual favColors; PhotosManual({required this.avatar, required this.favColors});} class FavColorsManual {final List<String> colors; FavColorsManual({required this.colors});}
这种方式不仅容易遗漏字段,还可能因类型转换(比如把int写成String)导致运行时错误,完全不适合复杂嵌套结构。
内容的提问来源于stack exchange,提问作者Heike Heinrich
相关产品推荐
相关产品推荐

