本文介绍如何在Flutter中创建HTTP网络请求和对请求的json string进行类型解析.

  • 网络请求

官方使用的是用dart io中的HttpClient发起的请求,但HttpClient本身功能较弱,很多常用功能都不支持。

建议使用dio 来发起网络请求,它是一个强大易用的dart http请求库,支持Restful API、FormData、拦截器、请求取消、Cookie管理、文件上传/下载……

dart:io 

发起HTTP请求

http支持位于dart:io,所以要创建一个HTTP client, 我们需要添加一个导入:

  1. import 'dart:io';
  2. var httpClient = new HttpClient();

该 client 支持常用的HTTP操作, such as GETPOSTPUTDELETE.

处理异步

注意,HTTP API 在返回值中使用了Dart Futures。 我们建议使用async/await语法来调用API。

网络调用通常遵循如下步骤:

  1. 创建 client.
  2. 构造 Uri.
  3. 发起请求, 等待请求,同时您也可以配置请求headers、 body。
  4. 关闭请求, 等待响应.
  5. 解码响应的内容.

Several of these steps use Future based APIs. Sample APIs calls for each step above are: 其中的几个步骤使用基于Future的API。上面步骤的示例:

  1. get() async {
  2. var httpClient = new HttpClient();
  3. var uri = new Uri.http(
  4. 'example.com', '/path1/path2', {'param1': '42', 'param2': 'foo'});
  5. var request = await httpClient.getUrl(uri);
  6. var response = await request.close();
  7. var responseBody = await response.transform(UTF8.decoder).join();
  8. }

dio

添加依赖

  1. dependencies:
  2. dio: ^x.x.x // latest version

发起一个 GET 请求 :

  1. Response response;
  2. response=await dio.get("/test?id=12&name=wendu")
  3. print(response.data.toString());
  4. // 请求参数也可以通过对象传递,上面的代码等同于:
  5. response=await dio.get("/test",data:{"id":12,"name":"wendu"})
  6. print(response.data.toString());

发起一个 POST 请求:

  1. response=await dio.post("/test",data:{"id":12,"name":"wendu"})

发起多个并发请求:

  1. response= await Future.wait([dio.post("/info"),dio.get("/token")]);

下载文件:

  1. response=await dio.download("https://www.google.com/","./xx.html")

发送 FormData:

  1. FormData formData = new FormData.from({
  2. "name": "wendux",
  3. "age": 25,
  4. });
  5. response = await dio.post("/info", data: formData)

通过FormData上传多个文件:

  1. FormData formData = new FormData.from({
  2. "name": "wendux",
  3. "age": 25,
  4. "file1": new UploadFileInfo(new File("./upload.txt"), "upload1.txt")
  5. "file2": new UploadFileInfo(new File("./upload.txt"), "upload2.txt")
  6. });
  7. response = await dio.post("/info", data: formData)
  • JSON解析

使用 dart:convert手动序列化JSON

Flutter中基本的JSON序列化非常简单。Flutter有一个内置dart:convert库,其中包含一个简单的JSON编码器和解码器。

以下是一个简单的user model的示例JSON。

  1. {
  2. "name": "John Smith",
  3. "email": "john@example.com"
  4. }

有了dart:convert,我们可以用两种方式来序列化这个JSON model。我们来看看这两种方法:

内连序列化JSON

通过查看dart:转换JSON文档,我们发现可以通过调用JSON.decode方法来解码JSON ,使用JSON字符串作为参数。

  1. Map<String, dynamic> user = JSON.decode(json);
  2. print('Howdy, ${user['name']}!');
  3. print('We sent the verification link to ${user['email']}.');

不幸的是,JSON.decode()仅返回一个Map<String, dynamic>,这意味着我们直到运行时才知道值的类型。 通过这种方法,我们失去了大部分静态类型语言特性:类型安全、自动补全和最重要的编译时异常。这样一来,我们的代码可能会变得非常容易出错。

例如,当我们访问nameemail字段时,我们输入的很快,导致字段名打错了。但由于这个JSON在map结构中,所以编译器不知道这个错误的字段名(译者语:所以编译时不会报错)。

在模型类中序列化JSON

我们可以通过引入一个简单的模型类(model class)来解决前面提到的问题,我们称之为User。在User类内部,我们有:

  • 一个User.fromJson 构造函数, 用于从一个map构造出一个 User实例 map structure
  • 一个toJson 方法, 将 User 实例转化为一个map.

这样,调用代码现在可以具有类型安全、自动补全字段(name和email)以及编译时异常。如果我们将拼写错误或字段视为int类型而不是String, 那么我们的应用程序就不会通过编译,而不是在运行时崩溃。

user.dart

  1. class User {
  2. final String name;
  3. final String email;
  4. User(this.name, this.email);
  5. User.fromJson(Map<String, dynamic> json)
  6. : name = json['name'],
  7. email = json['email'];
  8. Map<String, dynamic> toJson() =>
  9. {
  10. 'name': name,
  11. 'email': email,
  12. };
  13. }

现在,序列化逻辑移到了模型本身内部。采用这种新方法,我们可以非常容易地反序列化user。

  1. Map userMap = JSON.decode(json);
  2. var user = new User.fromJson(userMap);
  3. print('Howdy, ${user.name}!');
  4. print('We sent the verification link to ${user.email}.');

要序列化一个user,我们只是将该User对象传递给该JSON.encode方法。我们不需要手动调用toJson这个方法,因为JSON.encode已经为我们做了。

  1. String json = JSON.encode(user);

Json映射到对象

首先要借助一个工具jsonformat 工具下载地址

举一个例子 json文件,来自玩安卓网站

这是一个相对很复杂的json文件

用jsonview打开查看,这个json文件包含一个data的数组和两个变量,然后数组的每一项又包含一个数组和6个变量,然后下一级数组的每一项又包含一个数组和6个变量 

下面使用jsonformat 转换成dart bean文件

打开下载的jsonformat ,将json文件copy进去点击格式化 

右边的红色是我们要填写的类名称,对应关系像这样,这里分别填写 tree children children ,后两个相同,点击生成bean 

生成代码如下

  1. import 'dart:convert' show json;
  2. class tree {
  3. int errorCode;
  4. String errorMsg;
  5. List<children> data;
  6. tree(jsonStr) {
  7. var jsonRes = json.decode(jsonStr);
  8. errorCode = jsonRes['errorCode'];
  9. errorMsg = jsonRes['errorMsg'];
  10. data = [];
  11. for (var dataItem in jsonRes['data']){
  12. data.add(new children(dataItem));
  13. }
  14. }
  15. @override
  16. String toString() {
  17. return '{"errorCode": $errorCode,"errorMsg": ${errorMsg != null?'${json.encode(errorMsg)}':'null'},"data": $data}';
  18. }
  19. }
  20. class children {
  21. int courseId;
  22. int id;
  23. int order;
  24. int parentChapterId;
  25. int visible;
  26. String name;
  27. List<children> children;
  28. children(jsonRes) {
  29. courseId = jsonRes['courseId'];
  30. id = jsonRes['id'];
  31. order = jsonRes['order'];
  32. parentChapterId = jsonRes['parentChapterId'];
  33. visible = jsonRes['visible'];
  34. name = jsonRes['name'];
  35. children = [];
  36. for (var childrenItem in jsonRes['children']){
  37. children.add(new children(childrenItem));
  38. }
  39. }
  40. @override
  41. String toString() {
  42. return '{"courseId": $courseId,"id": $id,"order": $order,"parentChapterId": $parentChapterId,"visible": $visible,"name": ${name != null?'${json.encode(name)}':'null'},"children": $children}';
  43. }
  44. }
  45. class children {
  46. int courseId;
  47. int id;
  48. int order;
  49. int parentChapterId;
  50. int visible;
  51. String name;
  52. List<dynamic> children;
  53. children(jsonRes) {
  54. courseId = jsonRes['courseId'];
  55. id = jsonRes['id'];
  56. order = jsonRes['order'];
  57. parentChapterId = jsonRes['parentChapterId'];
  58. visible = jsonRes['visible'];
  59. name = jsonRes['name'];
  60. children = [];
  61. for (var childrenItem in jsonRes['children']){
  62. children.add(childrenItem);
  63. }
  64. }
  65. @override
  66. String toString() {
  67. return '{"courseId": $courseId,"id": $id,"order": $order,"parentChapterId": $parentChapterId,"visible": $visible,"name": ${name != null?'${json.encode(name)}':'null'},"children": $children}';
  68. }
  69. }

接下来就是在APP中请求网络,将其转换成dart bean

  1. ///封装的get请求 _networkUtil,可以替换成自己的请求方式
  2. ///发起get网络请求并且转换json
  3. Future<dynamic> requestGet(String url) {
  4. return http.get(url)
  5. .then((http.Response response) {
  6. final String res = response.body;
  7. final int statusCode = response.statusCode;
  8. if (statusCode < 200 || statusCode > 400 || json == null) {
  9. throw new Exception("Error while fetching data");
  10. }
  11. ///有值
  12. return _decoder.convert(res);
  13. });
  14. }
  15. ///这里返回的就是 Future<Tree> 对象,(fillUrl(TREE_LIST)是请求的url
  16. Future<Tree> fetchTree() {
  17. return _networkUtil.requestGet(fillUrl(TREE_LIST)).then((dynamic res) {
  18. ///可以这样取值
  19. return new Tree.map(res);
  20. });
  21. }
  1.  

Flutter网络请求与JSON解析的更多相关文章

  1. Android okHttp网络请求之Json解析

    前言: 前面两篇文章介绍了基于okHttp的post.get请求,以及文件的上传下载,今天主要介绍一下如何和Json解析一起使用?如何才能提高开发效率? okHttp相关文章地址: Android o ...

  2. Flutter网络请求和数据解析

    一:前言 - 什么是反射机制,Flutter为什么禁用反射机制? 在Flutter中它的网络请求和数据解析稍微的比较麻烦一点,因为Flutter不支持反射机制.相信大家都看到这么一条,就是Flutte ...

  3. C#网络请求与JSON解析

    最新学校的海康摄像头集控平台(网页端)不能在win10里登录,我寻思着拿海康的c# demo直接改. 首先得解决权限问题,每个教师任教不同年级,只能看到自己所在年级的设备,涉及到登录,在此记录一下C# ...

  4. iOS 自己封装的网络请求,json解析的类

    基本上所有的APP都会涉及网络这块,不管是用AFNetWorking还是自己写的http请求,整个网络框架的搭建很重要. 楼主封装的网络请求类,包括自己写的http请求和AFNetWorking的请求 ...

  5. 网络请求之JSON解析

    <一>JSON的基本知识 什么是JSON:JSON的全称是JavaScript Object Notation(JavaScript对象符号),是目前使用最广泛的数据交换格式,具有跨平台. ...

  6. Android网络请求与数据解析,使用Gson和GsonFormat解析复杂Json数据

    版权声明:未经博主允许不得转载 一:简介 [达叔有道]软件技术人员,时代作者,从 Android 到全栈之路,我相信你也可以!阅读他的文章,会上瘾!You and me, we are family ...

  7. 使用Charles进行网络请求抓包解析

    使用Charles进行网络请求抓包解析 0. 懒人的福音(⌐■_■)(破解版下载地址,记得安装java库支持) http://pan.baidu.com/s/1c08ksMW 1. 查看电脑的ip地址 ...

  8. Swift 网络请求数据与解析

    一: Swift 网络数据请求与处理最常用第三方 又有时间出来装天才了,还是在学swift,从中又发现一些问题,这两天上网找博客看问题弄的真的心都累.博客一篇写出来,好多就直接照抄,就没有实质性的把问 ...

  9. Flutter 网络请求库http

    http 集成http库 https://pub.dartlang.org/packages/http 添加依赖 dependencies: http: ^ 安装 flutter packages g ...

随机推荐

  1. lamp字符编码的转换规则

    1.lamp字符编码的转换规则 lamp(Linux+Apache+Mysql+PHP) 1.1GB 2312 GB 2312 或 GB 2312-80 是中国国家标准简体中文字符集,全称<信息 ...

  2. 【BZOJ 3238】【AHOI 2013】差异

    http://www.lydsy.com/JudgeOnline/problem.php?id=3238 后缀数组裸题但是\(5\times 10^5\)貌似常数有点大就过不了?(我的sa常数那么大想 ...

  3. [USACO 2016 Dec Gold] Tutorial

    Link: 传送门 A: 贪心从小到大插入,用并查集维护连通性 #include <bits/stdc++.h> using namespace std; #define X first ...

  4. poj 3225 Help with Intervals(线段树,区间更新)

    Help with Intervals Time Limit: 6000MS   Memory Limit: 131072K Total Submissions: 12474   Accepted:  ...

  5. 【欧拉回路】Play On Words(6-16)

    [UVA10129]Play On Words 算法入门经典第6章6-16(P169) 题目大意:有一些单词,问能不能将它们串成字符串(只有前缀和后缀相同才能连) 试题分析:很巧妙的一道题,将每个单词 ...

  6. HDU 6053 TrickGCD(分块)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=6053 [题目大意] 给出一个数列每个位置可以取到的最大值, 问这个可以构造多少个数列,使得他们的最 ...

  7. Android中Acition和Category常量表

    Action Action常量 对应字符串 简单说明 ACTION_MAIN android.intent.action.MAIN 应用程序入口 ACTION_VIEW android.intent. ...

  8. 设置Eclipse编码方式

    1.windows->Preferences...打开"首选项"对话框,左侧导航树,导航到 general->Workspace,右侧Text file encodin ...

  9. 计算标准差 Exercise07_11

    import java.util.Scanner; /** * @author 冰樱梦 * 时间:2018年下半年 * 题目:计算标准差 * */ public class Exercise07_11 ...

  10. insert into table(key)value('value') on duplicate key update key=value

    MYSQL篇 新增如果unique索引字段重复,则更新: insert into mg_user(key,key2,key3)value('value','value2','value3') on d ...