一.引入三个依赖
dependencies:
json_annotation: ^4.4.0
dev_dependencies:
build_runner: ^2.1.8
json_serializable: ^6.1.5
二.创建数据模型PersonModel
/// 1.引入json_annotation
import 'package:json_annotation/json_annotation.dart';
/// 2.指定此类的代码生成文件(格式:part '类名.g.dart';)
part 'person_model.g.dart';
/// 3.添加序列化标注
@JsonSerializable()
class PersonModel {
@JsonKey(name: 'first_name')
String? firstName;
@JsonKey(name: 'last_name')
String? lastName;
PersonModel({this.firstName, this.lastName});
/// 4.添加反序列化方法(格式:factory 类名.fromJson(Map<String, dynamic> json) => _$类名FromJson(json);)
factory PersonModel.fromJson(Map<String, dynamic> json) => _$PersonModelFromJson(json);
/// 5.添加序列化方法(格式:Map<String, dynamic> toJson() => _$类名ToJson(this);)
Map<String, dynamic> toJson() => _$PersonModelToJson(this);
}
三.生成对于的.g.dart文件
1.一次性构建
flutter packages pub run build_runner build
2.删除后重新构建
flutter packages pub run build_runner build --delete-conflicting-outputs
3.文件监听,自动为后续创建得实体类生成对应得.g.dart文件
flutter packages pub run build_runner watch
四.JsonKey
nullable:默认为true,表示该字段可为null。
defaultValue:如果源JSON不包含该key或该key的value为null,提供一个默认值。
name:别名,若为null则默认为字段名。
required:默认为false,若为真会检查JSON是否包含该key,若没有则抛出异常(key为null也是有效的)。
五.JsonConverter
/// 实现这个类为特定的[Type]提供自定义转换器。
///
/// [T]是需要转换的类型。
///
/// [S]是存储在JSON中的值的类型,必须是有效的JSON类型
/// 例如[String]、[int]或[Map<String, dynamic>]。
abstract class JsonConverter<T, S> {
const JsonConverter();
T fromJson(S json);
S toJson(T object);
}
例如下面一个文章json,里面的content_pic是一个字符串,需要转换为一个Model:
{
"id":28,
"content":"这是一篇主题区测试文章1",
"admiration_num":1,
"collect_num":1,
"comment_num":0,
"block":1,
"member_id":1,
"content_pic":"[{\"type\":\"image\",\"url\":\"https://storage.googleapis.com/mr486/topic/image/2022042020/62600304d24fd--compress.jpeg\"},{\"type\":\"video\",\"cover_url\":\"https://storage.googleapis.com/mr486/topic/video_cover/2022042020/62600304aa34e--compress.jpeg\",\"url\":\"https://storage.googleapis.com/mr486/topic/video/2022042020/6260030614271--1645415153.609362_o_IMG_0277.mp4\"}]"
}
@JsonSerializable()
class ArticleModel {
@JsonKey(name: 'id')
int? id;
@JsonKey(name: 'content_pic')
@_ArticleAssetConverter()
List<ArticleAssetModel>? contentAssets;
ArticleModel({
this.id,
this.contentAssets,
});
factory ArticleModel.fromJson(Map<String, dynamic> json) => _$ArticleModelFromJson(json);
Map<String, dynamic> toJson() => _$ArticleModelToJson(this);
}
class _ArticleAssetConverter implements JsonConverter<List<ArticleAssetModel>?, String?> {
const _ArticleAssetConverter();
@override
List<ArticleAssetModel>? fromJson(String? value) {
final List<ArticleAssetModel> models = [];
if (value.isNotBlank) {
final json = jsonDecode(value!);
if (json is List) {
/// 格式不对的数据剔除掉
for (final element in json) {
if (element is Map<String, dynamic>) {
models.add(ArticleAssetModel.fromJson(element));
}
}
}
}
return models;
}
@override
String? toJson(List<ArticleAssetModel>? object) {
// TODO: implement toJson
throw UnimplementedError();
}
}
@JsonSerializable()
class ArticleAssetModel {
@JsonKey(name: 'type')
String? type;
@JsonKey(name: 'url')
String? url;
@JsonKey(name: 'cover_url')
String? coverUrl;
ArticleAssetModel({
this.url,
this.type,
this.coverUrl
});
factory ArticleAssetModel.fromJson(Map<String, dynamic> json) => _$ArticleAssetModelFromJson(json);
Map<String, dynamic> toJson() => _$ArticleAssetModelToJson(this);
}
六.JsonEnum
fieldRename:定义名称转换时的命名策略,使用@JsonValue的值优先于该选项。
可以用JsonValue定义枚举的value特殊值,值类型可以为String或int。
/// 例如上述例子中[ArticleAssetModel]的[type]可以使用枚举定义
enum UploadFileType {
@JsonValue('image')
image,
@JsonValue('video')
video,
}
@JsonKey(name: 'type')
UploadFileType? type;
网友评论