Flutter

Flutter 使用json_annotation创建数据模型

2022-04-29  本文已影响0人  雨泽Sunshine

一.引入三个依赖

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

五.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

可以用JsonValue定义枚举的value特殊值,值类型可以为Stringint

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

@JsonKey(name: 'type')
UploadFileType? type;
上一篇下一篇

猜你喜欢

热点阅读