美文网首页移动端技术工作生活
Flutter开发中JSON和序列化

Flutter开发中JSON和序列化

作者: 海_3efc | 来源:发表于2019-07-03 13:53 被阅读0次

    Flutter开发过程中,经常需要进行对象进行JSON序列化,进行网络交互。由于Flutter中禁止使用反射,影响应用优化。

    常见的JSON序列化方式:

    • Flutter内置的dart:convert库;
    • 在模型类中序列化JSON,在类中手动添加fromJson()和toJson()函数;
    1.使用Flutter内置的dart:convert库

    首先需要引入import 'dart:convert'。该库内置了一个简单的JSON解码器和编码器。
    注:该内置Json序列化进行解码,仅支持json字符串转成Map<String,dynamic>。

    JSON对json字符串进行解码:

    String json = "{\"name\": \"John Smith\",\"email\": \"john@example.com\"}";
    Map<String ,dynamic> map = new JsonDecoder().convert(json);
    

    JSON对Map<String,dynamic>类型数据进行编码

    Map<String,dynamic> map ={"name": "John Smith","email": "john@example.com"};
    //支持object对象转成json字符串
    String json = new JsonEncoder().convert(map);
    

    以上就是Flutter内置的Json序列化的功能,如果仅简单的将对象转化成字符串,或者Map数据转成Json字符串,使用内置的功能即可满足。但是通常情况下我们在网络请求时需要将网络返回的一个Json字符串直接转化才一个Object对象,这时候内置的convert库就满足不了我们的需求,这个时候我们就需要自己进行将Map数据进行object化,即为Model(实体类)增加fromJson()toJson()函数。

    2.在模型类中序列化JSON

    在此使用一个简单的User模型来说明,并为User模型增加一个fromJson和toJson函数,如下:
    User.dart

     class User{
        String id;
        String name;
        int age;
      
        User(this.id,this.name,this.age);
        ///重点来了
        ///将Map转成User对象
        User.fromJson(Map<String,dynamic> map)
                    :id=map['id'],
                     name=map['name'],
                     age=map['age'];
        //将User对象转化成Map
        Map<String,dynamic> toJson()=>{
            'id'=id,
            'name'=name,
            'age'=age,
        };
    }
    

    这样我们就可以轻易的进行反序列化了,

    //转成User对象
    User user = User.fromJson(new JsonDecoder().convert(json));
    将User对象转成Map
    Map<String,dynamic> map = user.toJson();
    

    这样我们就可以进行轻易的将Object对象进行反序列化了。
    但是如果在每个Model中我们都要手动添加fromJson()toJson()函数的话,效率低不说而且还容易出错。那么有没有自动化的工具帮我们自动生成这两个函数呢,很幸运,有这么一款工具json_serializable package ,再次感受万能的注解。

    3.代码自动生成序列化JSON

    我们使用了json_serializable package包。 它是一个自动化的源代码生成器,可以为我们生成JSON序列化模板。
    由于序列化代码不再由我们手写和维护,我们将运行时产生JSON序列化异常的风险降至最低。

    1)首先在pubspec.yaml中引入库

    dependencies:
        json_annotation: ^2.4.0 
    
    //仅在开发过程中使用的库
    dev_dependencies:
       build_runner: ^1.0.0
      json_serializable: ^3.0.0
    
    

    2)编写model类并引入序列化的注解

    import 'package:json_annotation/json_annotation.dart';
    //声明该TokenModel.g.dart文件是当前类的一部分
    part 'TokenModel.g.dart';
    
    //自动化生成fromJson和toJson代码的关键性注解
    @JsonSerializable()
    class TokenModel{
    
      String token;
      String refreshToken;
      int tokenExpiryDate;
      int refreshTokenExpiryDate;
    
      TokenModel({this.token,this.refreshToken,this.tokenExpiryDate,this.refreshTokenExpiryDate});
    
      //_$TokenModelFromJson(json)为生成序列化对象的新函数名字
      factory TokenModel.fromJson(Map<String,dynamic> json) => _$TokenModelFromJson(json);
      //_$TokenModelToJson为生成的反序列化对象的新函数名字
      Map<String,dynamic> toJson() => _$TokenModelToJson(this);
    }
    

    此时会有几处报错:part 'TokenModel.g.dart'_$TokenModelFromJson(json)_$TokenModelToJson(this),没关系,这几处是通过注解生成的。下面我们就通过命令行执行命名生成新的TokenModel.g.dart文件。

    3)命令行执行命令自动生成序列化模板
    两种方式:

    • 一次性生成
      通过在我们的项目根目录下命令行运行flutter packages pub run build_runner build,我们可以在需要时为我们的model生成json序列化代码。 这触发了一次性构建,它通过我们的源文件,挑选相关的并为它们生成必要的序列化代码。
    • 持续性生成
      通过在我们的项目根目录下命令行运行:flutter packages pub run build_runner watch,该命令会在后台启动一次观察器_watch_,然后并让它在后台运行,这是安全的。这个观察器会监视我们项目中文件的变化,在需要时自动构建必要的文件。

    最后生成的文件如下:

    // GENERATED CODE - DO NOT MODIFY BY HAND
    
    part of 'TokenModel.dart';
    
    // **************************************************************************
    // JsonSerializableGenerator
    // **************************************************************************
    
    TokenModel _$TokenModelFromJson(Map<String, dynamic> json) {
      return TokenModel(
          token: json['token'] as String,
          refreshToken: json['refreshToken'] as String,
          tokenExpiryDate: json['tokenExpiryDate'] as int,
          refreshTokenExpiryDate: json['refreshTokenExpiryDate'] as int);
    }
    
    Map<String, dynamic> _$TokenModelToJson(TokenModel instance) =>
        <String, dynamic>{
          'token': instance.token,
          'refreshToken': instance.refreshToken,
          'tokenExpiryDate': instance.tokenExpiryDate,
          'refreshTokenExpiryDate': instance.refreshTokenExpiryDate
        };
    
    

    4)使用json_serializable生成的模型
    使用方式跟我们手动添加一样,如下:

    Map<String,dynamic> map = new JsonDecoder().convert(json);
    //转成TokenModel对象
    TokenModel token= TokenModel.fromJson(map);
    将TokenModel对象转成Map
    Map<String,dynamic> map2 = token.toJson();
    //将TokenModel对象转成json字符串
    String json0 = new JsonEncoder().convert(token);
    

    有了json_serializable,我们就不用手动添加fromJson()toJson()函数了,提高了开发效率,也降低了错误率。

    参考文档

    相关文章

      网友评论

        本文标题:Flutter开发中JSON和序列化

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