美文网首页Flutter
Flutter 使用json_annotation创建数据模型

Flutter 使用json_annotation创建数据模型

作者: 雨泽Sunshine | 来源:发表于2022-04-29 16:56 被阅读0次

    一.引入三个依赖

    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也是有效的)。

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

    相关文章

      网友评论

        本文标题:Flutter 使用json_annotation创建数据模型

        本文链接:https://www.haomeiwen.com/subject/nhdiertx.html