Flutter 使用json_annotation创建数据模型

一.引入三个依赖

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或该keyvaluenull,提供一个默认值。
  • name:别名,若为null则默认为字段名。
  • required:默认为false,若为真会检查JSON是否包含该key,若没有则抛出异常(keynull也是有效的)。
  • 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特殊值,值类型可以为Stringint

/// 例如上述例子中[ArticleAssetModel]的[type]可以使用枚举定义
enum UploadFileType {
  @JsonValue('image')
  image,
  @JsonValue('video')
  video,
}

@JsonKey(name: 'type')
UploadFileType? type;
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容