Flutter网络请求与JSON解析
本文介绍如何在Flutter中创建HTTP网络请求和对请求的json string进行类型解析.
网络请求
官方使用的是用dart io中的HttpClient发起的请求,但HttpClient本身功能较弱,很多常用功能都不支持。
建议使用dio 来发起网络请求,它是一个强大易用的dart http请求库,支持Restful API、FormData、拦截器、请求取消、Cookie管理、文件上传/下载……
dart:io
发起HTTP请求
http支持位于dart:io,所以要创建一个HTTP client, 我们需要添加一个导入:
import 'dart:io';
var httpClient = new HttpClient();
该 client 支持常用的HTTP操作, such as GET, POST, PUT, DELETE.
处理异步
注意,HTTP API 在返回值中使用了Dart Futures。 我们建议使用async/await语法来调用API。
网络调用通常遵循如下步骤:
- 创建 client.
- 构造 Uri.
- 发起请求, 等待请求,同时您也可以配置请求headers、 body。
- 关闭请求, 等待响应.
- 解码响应的内容.
Several of these steps use Future based APIs. Sample APIs calls for each step above are: 其中的几个步骤使用基于Future的API。上面步骤的示例:
get() async {
var httpClient = new HttpClient();
var uri = new Uri.http(
'example.com', '/path1/path2', {'param1': '42', 'param2': 'foo'});
var request = await httpClient.getUrl(uri);
var response = await request.close();
var responseBody = await response.transform(UTF8.decoder).join();
}
dio
添加依赖
dependencies:
dio: ^x.x.x // latest version
发起一个 GET 请求 :
Response response;
response=await dio.get("/test?id=12&name=wendu")
print(response.data.toString());
// 请求参数也可以通过对象传递,上面的代码等同于:
response=await dio.get("/test",data:{"id":12,"name":"wendu"})
print(response.data.toString());
发起一个 POST 请求:
response=await dio.post("/test",data:{"id":12,"name":"wendu"})
发起多个并发请求:
response= await Future.wait([dio.post("/info"),dio.get("/token")]);
下载文件:
response=await dio.download("https://www.google.com/","./xx.html")
发送 FormData:
FormData formData = new FormData.from({
"name": "wendux",
"age": 25,
});
response = await dio.post("/info", data: formData)
通过FormData上传多个文件:
FormData formData = new FormData.from({
"name": "wendux",
"age": 25,
"file1": new UploadFileInfo(new File("./upload.txt"), "upload1.txt")
"file2": new UploadFileInfo(new File("./upload.txt"), "upload2.txt")
});
response = await dio.post("/info", data: formData)
JSON解析
使用 dart:convert手动序列化JSON
Flutter中基本的JSON序列化非常简单。Flutter有一个内置dart:convert库,其中包含一个简单的JSON编码器和解码器。
以下是一个简单的user model的示例JSON。
{
"name": "John Smith",
"email": "john@example.com"
}
有了dart:convert,我们可以用两种方式来序列化这个JSON model。我们来看看这两种方法:
内连序列化JSON
通过查看dart:转换JSON文档,我们发现可以通过调用JSON.decode方法来解码JSON ,使用JSON字符串作为参数。
Map<String, dynamic> user = JSON.decode(json);
print('Howdy, ${user['name']}!');
print('We sent the verification link to ${user['email']}.');
不幸的是,JSON.decode()仅返回一个Map<String, dynamic>,这意味着我们直到运行时才知道值的类型。 通过这种方法,我们失去了大部分静态类型语言特性:类型安全、自动补全和最重要的编译时异常。这样一来,我们的代码可能会变得非常容易出错。
例如,当我们访问name或email字段时,我们输入的很快,导致字段名打错了。但由于这个JSON在map结构中,所以编译器不知道这个错误的字段名(译者语:所以编译时不会报错)。
在模型类中序列化JSON
我们可以通过引入一个简单的模型类(model class)来解决前面提到的问题,我们称之为User。在User类内部,我们有:
- 一个
User.fromJson构造函数, 用于从一个map构造出一个User实例 map structure - 一个
toJson方法, 将User实例转化为一个map.
这样,调用代码现在可以具有类型安全、自动补全字段(name和email)以及编译时异常。如果我们将拼写错误或字段视为int类型而不是String, 那么我们的应用程序就不会通过编译,而不是在运行时崩溃。
user.dart
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。
Map userMap = JSON.decode(json);
var user = new User.fromJson(userMap);
print('Howdy, ${user.name}!');
print('We sent the verification link to ${user.email}.');
要序列化一个user,我们只是将该User对象传递给该JSON.encode方法。我们不需要手动调用toJson这个方法,因为JSON.encode已经为我们做了。
String json = JSON.encode(user);
Json映射到对象
首先要借助一个工具jsonformat 工具下载地址
举一个例子 json文件,来自玩安卓网站
这是一个相对很复杂的json文件
用jsonview打开查看,这个json文件包含一个data的数组和两个变量,然后数组的每一项又包含一个数组和6个变量,然后下一级数组的每一项又包含一个数组和6个变量
下面使用jsonformat 转换成dart bean文件
打开下载的jsonformat ,将json文件copy进去点击格式化
右边的红色是我们要填写的类名称,对应关系像这样,这里分别填写 tree children children ,后两个相同,点击生成bean
生成代码如下
import 'dart:convert' show json;
class tree {
int errorCode;
String errorMsg;
List<children> data;
tree(jsonStr) {
var jsonRes = json.decode(jsonStr);
errorCode = jsonRes['errorCode'];
errorMsg = jsonRes['errorMsg'];
data = [];
for (var dataItem in jsonRes['data']){
data.add(new children(dataItem));
}
}
@override
String toString() {
return '{"errorCode": $errorCode,"errorMsg": ${errorMsg != null?'${json.encode(errorMsg)}':'null'},"data": $data}';
}
}
class children {
int courseId;
int id;
int order;
int parentChapterId;
int visible;
String name;
List<children> children;
children(jsonRes) {
courseId = jsonRes['courseId'];
id = jsonRes['id'];
order = jsonRes['order'];
parentChapterId = jsonRes['parentChapterId'];
visible = jsonRes['visible'];
name = jsonRes['name'];
children = [];
for (var childrenItem in jsonRes['children']){
children.add(new children(childrenItem));
}
}
@override
String toString() {
return '{"courseId": $courseId,"id": $id,"order": $order,"parentChapterId": $parentChapterId,"visible": $visible,"name": ${name != null?'${json.encode(name)}':'null'},"children": $children}';
}
}
class children {
int courseId;
int id;
int order;
int parentChapterId;
int visible;
String name;
List<dynamic> children;
children(jsonRes) {
courseId = jsonRes['courseId'];
id = jsonRes['id'];
order = jsonRes['order'];
parentChapterId = jsonRes['parentChapterId'];
visible = jsonRes['visible'];
name = jsonRes['name'];
children = [];
for (var childrenItem in jsonRes['children']){
children.add(childrenItem);
}
}
@override
String toString() {
return '{"courseId": $courseId,"id": $id,"order": $order,"parentChapterId": $parentChapterId,"visible": $visible,"name": ${name != null?'${json.encode(name)}':'null'},"children": $children}';
}
}
接下来就是在APP中请求网络,将其转换成dart bean
///封装的get请求 _networkUtil,可以替换成自己的请求方式
///发起get网络请求并且转换json
Future<dynamic> requestGet(String url) {
return http.get(url)
.then((http.Response response) {
final String res = response.body;
final int statusCode = response.statusCode;
if (statusCode < 200 || statusCode > 400 || json == null) {
throw new Exception("Error while fetching data");
}
///有值
return _decoder.convert(res);
});
}
///这里返回的就是 Future<Tree> 对象,(fillUrl(TREE_LIST)是请求的url
Future<Tree> fetchTree() {
return _networkUtil.requestGet(fillUrl(TREE_LIST)).then((dynamic res) {
///可以这样取值
return new Tree.map(res);
});
}
Flutter网络请求与JSON解析的更多相关文章
- Android okHttp网络请求之Json解析
前言: 前面两篇文章介绍了基于okHttp的post.get请求,以及文件的上传下载,今天主要介绍一下如何和Json解析一起使用?如何才能提高开发效率? okHttp相关文章地址: Android o ...
- Flutter网络请求和数据解析
一:前言 - 什么是反射机制,Flutter为什么禁用反射机制? 在Flutter中它的网络请求和数据解析稍微的比较麻烦一点,因为Flutter不支持反射机制.相信大家都看到这么一条,就是Flutte ...
- C#网络请求与JSON解析
最新学校的海康摄像头集控平台(网页端)不能在win10里登录,我寻思着拿海康的c# demo直接改. 首先得解决权限问题,每个教师任教不同年级,只能看到自己所在年级的设备,涉及到登录,在此记录一下C# ...
- iOS 自己封装的网络请求,json解析的类
基本上所有的APP都会涉及网络这块,不管是用AFNetWorking还是自己写的http请求,整个网络框架的搭建很重要. 楼主封装的网络请求类,包括自己写的http请求和AFNetWorking的请求 ...
- 网络请求之JSON解析
<一>JSON的基本知识 什么是JSON:JSON的全称是JavaScript Object Notation(JavaScript对象符号),是目前使用最广泛的数据交换格式,具有跨平台. ...
- Android网络请求与数据解析,使用Gson和GsonFormat解析复杂Json数据
版权声明:未经博主允许不得转载 一:简介 [达叔有道]软件技术人员,时代作者,从 Android 到全栈之路,我相信你也可以!阅读他的文章,会上瘾!You and me, we are family ...
- 使用Charles进行网络请求抓包解析
使用Charles进行网络请求抓包解析 0. 懒人的福音(⌐■_■)(破解版下载地址,记得安装java库支持) http://pan.baidu.com/s/1c08ksMW 1. 查看电脑的ip地址 ...
- Swift 网络请求数据与解析
一: Swift 网络数据请求与处理最常用第三方 又有时间出来装天才了,还是在学swift,从中又发现一些问题,这两天上网找博客看问题弄的真的心都累.博客一篇写出来,好多就直接照抄,就没有实质性的把问 ...
- Flutter 网络请求库http
http 集成http库 https://pub.dartlang.org/packages/http 添加依赖 dependencies: http: ^ 安装 flutter packages g ...
随机推荐
- 牛客练习赛 29 E 位运算?位运算!(线段树)
题目链接 牛客练习赛29E 对$20$位分别建立线段树.首先$1$和$2$可以合起来搞(左移右移其实是等效的) 用个lazy标记下.转移的时候加个中间变量. $3$和$4$其实就是区间$01$覆盖操 ...
- 判断数独是否合法(LintCode)
判断数独是否合法 请判定一个数独是否有效. 该数独可能只填充了部分数字,其中缺少的数字用. 表示. 样例 下列就是一个合法数独的样例. 注意 一个合法的数独(仅部分填充)并不一定是可解的.我们仅需使填 ...
- Flask实战第48天:首页轮播图实现
首页的布局如下 因为以后所有的内容都是在main-container里面,所以这里我们修改front_base.html,把{% block body%}{% endblock%}放到里面去 < ...
- Luogu P3960 列队 线段树
题面 线段树入门题. 我们考虑线段树来维护这个矩阵. 首先我们先定n+1棵线段树前n棵维护每行前m-1个同学中没有离队过的同学,还有一棵维护第m列中没有离队过的同学.再定n+1棵线段树前n棵线段树维护 ...
- 【二分答案】【最大流】[HNOI2007]紧急疏散EVACUATE
[HNOI2007]紧急疏散EVACUATE 题目描述 发生了火警,所有人员需要紧急疏散!假设每个房间是一个N M的矩形区域.每个格子如果是'.',那么表示这是一块空地:如果是'X',那么表示这是一面 ...
- BZOJ 1934 [Shoi2007]Vote 善意的投票(最小割)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1934 [题目大意] 每个人对于投票都有自己原来的观点:1或者0, 他可以违背自己原来的 ...
- 【二分】Codeforces Round #404 (Div. 2) C. Anton and Fairy Tale
当m>=n时,显然答案是n: 若m<n,在第m天之后,每天粮仓减少的量会形成等差数列,只需要二分到底在第几天,粮仓第一次下降到0即可. 若直接解不等式,可能会有误差,需要在答案旁边扫一下. ...
- 【动态规划技巧题】POJ2229-Sumsets
[题目大意] 把一个数n分成2的指数幂相加的形式,问有几种情况. [思路] 如果当前i为奇数,则必定有至少一个1,可以看作i-1的情形再加上一个1.即f[i]=f[i-1]. 如果当前i为偶数,假设没 ...
- java 的环境搭建
java.JDK 的搭建__本人是在360里下载的.也可以去其它的网站. java.jdk官网地址下载: https://download.oracle.com 二.也可以下载地址:http://do ...
- codevs 1080 线段树练习--用树状数组做的
1080 线段树练习 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 一行N个方格,开始每个格子里都有一个整数.现在动态 ...