目前手上开发的项目,出于便于维护的角度考虑,选择了可以跨端的Flutter进行开发。
作为一个Android开发er,使用dart这种语言进行开发还是多少有些不习惯。大家都知道,Java中对JSON进行序列化的库有很多,比如Gson,FastJson,都可以快速将JSON字符串转成对象——然而在flutter中却没有这么简单。
这些库的原理运用到了反射机制,而反射机制在flutter中是被禁用的。(虽然dart语言有反射机制)
这里记录一下flutter在使用时对JSON进行序列化的方法
flutter中有两种常用的策略:
模型类User.dart
class User {
final String name;
final String email;
User(this.name, this.email);
User.fromJson(Map json)
: name = json['name'],
email = json['email'];
Map toJson() => {
'name': name,
'email': email,
};
}
获取User实例:
Map userMap = jsonDecode(jsonString);
var user = User.fromJson(userMap);
将User实例转为JSON:
String json = jsonEncode(user);
PS: User.fromJson() 和 User.toJson() 方法最好进行单元测试验证。
除了json_serializable之外, built_Value也可以进行JSON序列化,且提供了更高层次的方法,让定义为不可变的类也能够被序列化为JSON。
在项目中配置json_serializable需要一个常规依赖,以及两个 dev 依赖。(dev 依赖 是不包括在App源代码中的依赖——即会被用在开发环境中)
pubspec.yaml文件:
dependencies:
# Your other regular dependencies here
json_annotation:
dev_dependencies:
# Your other dev_dependencies here
build_runner:
json_serializable:
在实体类User.dart上加注解@JsonSerializable(),
import 'package:json_annotation/json_annotation.dart';
part 'user.g.dart';
@JsonSerializable()
class User {
User(this.name, this.email);
String name;
String email;
factory User.fromJson(Map json) => _$UserFromJson(json);
Map toJson() => _$UserToJson(this);
}
如果需要,可以自定义命名策略,如:
@JsonKey(name: 'registration_date_millis')
final int registrationDateMillis;
@JsonKey 声明方法包括:
const JsonKey({
this.defaultValue,
this.disallowNullValue,
this.fromJson,//自定义该字段fromJson的方法
this.ignore,//使用json_serializable生成时忽略该字段
this.includeIfNull,
this.name,//自定义命名策略
this.nullable,
this.required,//要求如果JSON中不存在该字段,则会抛出异常
this.toJson,//自定义该字段toJson的方法
this.unknownEnumValue,
});
在项目根目录运行如下代码
一次性代码生成:
flutter pub run build_runner build
持续代码生成:
flutter pub run build_runner watch
该方法会监听项目中的文件变化,自动构建文件。
在实体类的注解中加入explicitToJson:true参数:
@JsonSerializable(explicitToJson: true)
class User{
User(this.name,this.address);
String name;
Address address;
factory User.fromJson(Map json) => _$UserFromJson(json);
Map toJson() => _$UserToJson(this);
}