zoukankan      html  css  js  c++  java
  • Flutter 中 JSON 解析

    本文介绍一下Flutter中如何进行json数据的解析。在移动端开发中,请求服务端返回json数据并解析是一个很常见的使用场景。Android原生开发中,有GsonFormat这样的神器,一键生成JavaBean,并利用Gson实现json数据和对象的转化;在React Native中更是得益于直接使用javascript语言,无需对json对象进行解析便可以直接访问属性。那么在Flutter中如何实现对json数据的解析呢?
    Flutter采用dart语言进行开发,dart具有很多核心库,其中dart:convert库中内置了json转换器,可以实现将json数据转换成dart对象。简单的使用如下:

    import 'dart:convert';
    
    void main() {
      // 解析对象
      String jsonStr1 = '{"name":"Curry","email":"SC@GSW.com"}';
      Map<String, dynamic> map = json.decode(jsonStr1);
      print(map['name']);
    
      // 解析列表
      String jsonStr2 = '[{"name":"Curry"},{"name":"Thompson"}]';
      List list = json.decode(jsonStr2);
      // 输出列表第一个对象的"name"属性
      print(list[0]["name"]);
    }
    

    解析json串的方法很简单,直接调用json.decode()即可,但是由于json.decode()方法返回类型为dynamic,因此无法进行类型的检查,编译时不会报错,容易使程序发生错误。采取的做法是像原生开发一样,新建一个model实体类,将json转为实体类对象。生成实体类的方法有以下两种:

    方法一.手写实体类

    一个简单的实体类实例如下

    class User{
      final String name;
      final String email;
    
      User(this.name,this.email);
    
      // 命名构造函数
      User.fromJson(Map<String, dynamic> json)
          : name = json['name'],
            email = json['email'];
    
      Map<String,dynamic> toJson() =>{
        'name':name,
        'email':email
      };
    }
    

    实体类中需要添加两个方法:User.fromJson和toJson,其中,User.fromJson是一个命名构造函数,通过传入的map构造出实体类对象;toJson()方法用于将实体类对象序列化为json字符串。
    使用方法如下:

    import 'dart:convert';
    // 这里需要替换为实体类所在路径
    import 'package:json_parse_test/user.dart';
    
    void main() {
      // 解析对象
      String jsonStr1 = '{"name":"Curry","email":"SC@GSW.com"}';
      Map<String, dynamic> map = json.decode(jsonStr1);
      User user = User.fromJson(map);
      print(user.name);
    
      // 解析列表
      String jsonStr2 = '[{"name":"Curry"},{"name":"Thompson"}]';
      List list= json.decode(jsonStr2);
      // 将列表中的第一个对象转换成User对象
      print(User.fromJson(list[0]).name);
      
      // 将对象序列化为json串
      // json.encode()会自动调用实体类中的toJson()
      String jsonText = json.encode(user);
      print(jsonText); 
    }
    

    这样就完成了将json转化成实体对象,步骤很简单,但是还有一个问题是,真的每个实体类都要我们自己去手写吗,有没有类似GsonFormat这种一键生成实体类的插件呢。当然是有的,之前从鸿洋大神推荐的Flutter学习资源中偶然发现了一个神奇的网站:
    https://javiercbk.github.io/json_to_dart/

     
    JSON To Dart.png

    可以直接通过json生成实体类代码,仿佛是发现了新大陆,不得不佩服开发出这些快捷工具的大神们,为后面学习的人铺平了道路。网站的操作很简单,一看就会。

    方法二.通过json_serializable自动生成

    json_serializable是Google官方推荐的一个json序列化库。使用之前需要在pubspec.yaml文件中添加依赖项:
    pubspec.yaml

    dependencies:
      # Your other regular dependencies here
      json_annotation: ^2.0.0
    
    dev_dependencies:
      # Your other dev_dependencies here
      build_runner: ^1.0.0
      json_serializable: ^2.0.0
    

    添加之后在项目根目录文件夹中运行flutter packages get (或者在编辑器中点击 “Packages Get”) 以在项目中使用这些新的依赖项。
    使用时也是需要新建一个实体类

    import 'package:json_annotation/json_annotation.dart';
    
    // user.g.dart通过命令自动生成
    part 'user_model.g.dart';
    
    @JsonSerializable()
    class User {
      // 自定义json字段名对应的属性名,不是必须的
      @JsonKey(name: 'userName')
      String name;
      String email;
    
      User(this.name, this.email);
    
      factory User.fromJson(Map<String, dynamic> json) =>
          _$UserFromJson(json);
    
      Map<String, dynamic> toJson() => _$UserToJson(this);
    }
    

    需要我们手写的就这些,这时代码会报错,我们需要运行命令来自动生成缺少的文件,有两种生成的方法:

    • 一次性生成
      在项目根目录文件夹下运行
    flutter packages pub run build_runner build
    
    • 持续生成
      在项目根目录文件夹下运行
    flutter packages pub run build_runner watch
    

    两者的区别是,一次性生成只执行一次,后面每新建一个实体类都需要重新运行该命令;持续生成会在我们编写代码的过程中根据需要自动生成缺少的文件。
    之后解析json的方法和方法一相同

    import 'dart:convert';
    // 这里需要替换为实体类所在路径
    import 'package:json_parse_test/user.dart';
    
    void main() {
      // 解析对象
      String jsonStr = '{"name":"Curry","email":"SC@GSW.com"}';
      Map<String, dynamic> map = json.decode(jsonStr);
      User user = User.fromJson(map);
      print(user.name);
    }
    

    这里关于实体类的生成我找到了做人要简单这位大神写的网页工具,同样是可以很方便地将json转换成实体类代码。

     
    json_serializable实体类生成工具

    生成代码后点击下载将实体类dart文件下载到本地,之后放到项目中,在项目根目录运行上面提到的生成文件命令即可。
    当然也可以通过自已定义模板编写脚本来生成实体类文件,具体做法可以参考《Flutter实战》

    总结

    Flutter中json的解析分为两步:
    1.通过json.decode()将json串转换成dart对象(Map或List)
    2.编写实体类(两种方法,手写或自动生成),利用上一步得到的dart对象构造出实体类对象
    其实在实际的应用中,我们从服务端返回的响应数据已经通过了网络请求框架的封装,比如很常用的Dio,我们可以直接从返回的响应中获取到dart对象,省去了第一步,直接转化成实体类对象即可。



    链接:https://www.jianshu.com/p/830ecb047d3d

  • 相关阅读:
    Codeforces Round #234A
    Java中的字符串
    Codeforces Round #376A (div2)
    node源码详解 (一)
    node源码详解(三)
    node源码详解(四)
    修改bootstrap modal模态框的宽度
    Bootstrap 模态框(Modal)插件
    JavaScript局部变量和全局变量的理解
    Javascript:谈谈JS的全局变量跟局部变量
  • 原文地址:https://www.cnblogs.com/ckAng/p/10442004.html
Copyright © 2011-2022 走看看