
























在现代移动应用开发中,与服务器进行数据交互是必不可少的功能。JSON(JavaScript Object Notation)作为一种轻量级的数据交换格式,因其易读性、简洁性和广泛支持性,已成为前后端通信的事实标准。在 Flutter 开发中,我们经常需要将 JSON 数据转换为 Dart 对象(反序列化),或将 Dart 对象转换为 JSON 数据(序列化)。
json_serializable 是一个基于Dart构建系统的代码生成库,它通过注解驱动的方式,自动为你的模型类生成序列化代码。它的核心优势在于:
dependencies:
flutter:
sdk: flutter
json_annotation: ^4.9.0 # 提供必要的注解
dev_dependencies:
build_runner: ^2.5.4 # 代码生成工具
json_serializable: ^6.9.5 # 序列化代码生成器
1. 创建基础模型类
import 'package:json_annotation/json_annotation.dart';
// 这个文件是自动生成的,必须声明part
part 'token.g.dart';
// 核心注解,表示这个类需要生成序列化代码
@JsonSerializable()
class Token {
final String accessToken;
final int expiresIn;
final String refreshToken;
Token({required this.accessToken, required this.expiresIn, required this.refreshToken});
/// 从 JSON 映射创建 Token 实例的工厂构造函数
factory Token.fromJson(Map<String, dynamic> json) => _$TokenFromJson(json);
/// 将 Token 实例转换为 JSON 映射的方法
Map<String, dynamic> toJson() => _$TokenToJson(this);
}
关键点说明:
2. 生成序列化代码
配置好模型类后,我们需要运行代码生成器。在项目根目录执行:
flutter pub run build_runner build
这个命令会:
对于大型项目,推荐使用watch模式,它会监听文件变化并自动重新生成代码:
flutter pub run build_runner watch
json_serializable 提供了丰富的配置选项,通过 @JsonKey 注解可以精细控制每个字段的序列化行为:
@JsonSerializable()
class AdvancedUser {
@JsonKey(name: 'user_name') // 自定义JSON字段名
final String name;
@JsonKey(ignore: true) // 忽略此字段,不参与序列化
final String? temporaryToken;
@JsonKey(defaultValue: 'unknown') // 默认值
final String status;
@JsonKey(fromJson: _parseBalance, toJson: _stringifyBalance) // 自定义转换
final double balance;
@JsonKey(includeIfNull: false) // 为null时不包含在JSON中
final String? nickname;
AdvancedUser({
required this.name,
this.temporaryToken,
this.status = 'unknown',
required this.balance,
this.nickname,
});
static double _parseBalance(String json) => double.parse(json);
static String _stringifyBalance(double balance) => balance.toStringAsFixed(2);
// ... fromJson/toJson方法
}
现实项目中的数据往往具有复杂的嵌套结构,json_serializable 可以优雅地处理这种情况:
@JsonSerializable()
class Address {
final String street;
final String city;
final String zipCode;
Address({required this.street, required this.city, required this.zipCode});
factory Address.fromJson(Map<String, dynamic> json) => _$AddressFromJson(json);
Map<String, dynamic> toJson() => _$AddressToJson(this);
}
@JsonSerializable()
class Company {
final String name;
final Address address;
Company({required this.name, required this.address});
factory Company.fromJson(Map<String, dynamic> json) => _$CompanyFromJson(json);
Map<String, dynamic> toJson() => _$CompanyToJson(this);
}
@JsonSerializable()
class Employee {
final String id;
final String name;
final Company company;
final List<String> skills; // 简单列表
final List<Address> previousAddresses; // 复杂对象列表
Employee({
required this.id,
required this.name,
required this.company,
required this.skills,
required this.previousAddresses,
});
factory Employee.fromJson(Map<String, dynamic> json) => _$EmployeeFromJson(json);
Map<String, dynamic> toJson() => _$EmployeeToJson(this);
}
json_serializable 对枚举和泛型也有很好的支持:
enum UserRole {
@JsonValue('admin')
admin,
@JsonValue('editor')
editor,
@JsonValue('viewer')
viewer,
@JsonValue('guest')
guest,
}
@JsonSerializable(genericArgumentFactories: true) // 启用泛型支持
class PaginatedResponse<T> {
final int page;
final int totalPages;
final List<T> data;
PaginatedResponse({
required this.page,
required this.totalPages,
required this.data,
});
factory PaginatedResponse.fromJson(
Map<String, dynamic> json,
T Function(Object? json) fromJsonT,
) => _$PaginatedResponseFromJson(json, fromJsonT);
Map<String, dynamic> toJson(Object? Function(T value) toJsonT) =>
_$PaginatedResponseToJson(this, toJsonT);
}
// 使用示例
final userResponse = PaginatedResponse<User>.fromJson(
jsonMap,
(json) => User.fromJson(json as Map<String, dynamic>),
);
DateTime 类型的处理
@JsonKey(fromJson: _dateFromJson, toJson: _dateToJson)
final DateTime createdAt;
static DateTime _dateFromJson(String json) => DateTime.parse(json);
static String _dateToJson(DateTime date) => date.toIso8601String();
处理可能为 null 的字段
@JsonSerializable()
class Product {
final String id;
final String name;
final String? description; // 可空字段
Product({required this.id, required this.name, this.description});
factory Product.fromJson(Map<String, dynamic> json) => _$ProductFromJson(json);
Map<String, dynamic> toJson() => _$ProductToJson(this);
}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。