一.引入三个依赖
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
也是有效的)。 -
unknownEnumValue
:当提供的值不在枚举字段中时,将会使用该默认值。JsonKey.nullForUndefinedEnumValue
是当遇到未定义的值时默认值为null。 -
fromJson
: 通过一个顶层方法将JSON
数据转换为自己想要的数据类型,例如:服务器返回的1为true
、2为false
转为bool
类型:
bool boolFromInt(int? value) => value == 1;
// ignore: avoid_positional_boolean_parameters
int boolToInt(bool? value) => (value ?? false) ? 1 : 2;
/// 是否未读
@JsonKey(name: 'is_unread', fromJson: boolFromInt, toJson: boolToInt)
bool? isUnread;
-
readValue
:用于从源JSON
里面读取映射值,例如读取Map
里面的多层映射值:
"data": {
"list": {
"item": [
{
"id": 2,
"name": "名字",
}
],
"total": 1
}
}
/// 上面的JSON我们只需要里面的list数组,但是服务器多返回一层item包裹了,此时我们可以使用readValue
Object? listMapper(Map json, String field) => (json['list'] as Map)['item'];
@JsonKey(readValue: listMapper)
List<ActivityModel>? list;
五.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;