对于 JSON 格式的数据交互,想必大家不会陌生。JSON(全称 JavaScript Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式,JSON 因为具有易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率等特性,通常被用在客户端与服务端的数据交互中。
对于 JSON 的基本知识,本文不做详细介绍,读者可以自行搜索资料进行学习。
手动解析
手动解析通常应用在一些基本简单的场合,即数据结构不是很复杂的场景,手动解析 JSON 是指使用 Flutter 提供的 dart:convert
中内置的 JSON 解码器。它能够将原始 JSON 字符串传递给 json.decode() 方法,然后在返回的 Map<String, dynamic> 中查找所需的值。它不需要依赖任何第三方库,对于小项目来说很方便。
例如,有下面一个接口:https://jsonplaceholder.typic…,它的数据格式如下:
{
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
"body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
}
由于上面的数据格式比较简单,因此我们可以使用手动解析的方式来解析它。
final responseJson = json.decode(response.body);
Map<String, dynamic> newTitle = responseJson ;
print(newTitle['title']);// 打印 title 的值
当然,我们也可以新建一个实体类,然后将它解析到实体类中。
final responseJson = json.decode(response.body);
print(responseJson.toString());
Post postBean = Post.fromJson(responseJson); //Post 为实体类
对于数据结构不是很复杂的时候,使用 fromJson 来解析字段还好,但是如果数据结构比较复杂的话,手写 fromJson、toJson 就不太友好,并且容易出错。
借助工具解析
在 Android 原生开发中,我们可以使用诸如 Gson、FastJson 等第三方库来帮助我们将 JSON 数据转成实体类。同样,在 Flutter 开发中,我们也可以使用插件或工具来一键生成实体类。
例如,下面是豆瓣电影提供的获取电影列表的一个接口,数据返回的格式如下:
{
count: 10,
start: 25,
total: 250,
subjects: [
{
rating: {
max: 10,
average: 9.1,
details: {
},
stars: "45",
min: 0
},
genres: [
"剧情",
"动作",
"科幻"
],
title: "蝙蝠侠:黑暗骑士",
casts: [
{
avatars: {
small: "http://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1004.webp",
large: "http://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1004.webp",
medium: "http://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1004.webp"
},
name_en: "Christian Bale",
name: "克里斯蒂安·贝尔",
alt: "https://movie.douban.com/celebrity/1005773/",
id: "1005773"
},
{
avatars: {
small: "http://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p13801.webp",
large: "http://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p13801.webp",
medium: "http://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p13801.webp"
},
name_en: "Heath Ledger",
name: "希斯·莱杰",
alt: "https://movie.douban.com/celebrity/1006957/",
id: "1006957"
},
{
avatars: {
small: "http://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p522.webp",
large: "http://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p522.webp",
medium: "http://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p522.webp"
},
name_en: "Aaron Eckhart",
name: "艾伦·艾克哈特",
alt: "https://movie.douban.com/celebrity/1053577/",
id: "1053577"
}
],
durations: ["152 分钟"],
collect_count: 813292,
mainland_pubdate: "",
has_video: true,
original_title: "The Dark Knight",
subtype: "movie",
directors: [
{
avatars: {
small: "http://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p673.webp",
large: "http://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p673.webp",
medium: "http://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p673.webp"
},
name_en: "Christopher Nolan",
name: "克里斯托弗·诺兰",
alt: "https://movie.douban.com/celebrity/1054524/",
id: "1054524"
}
],
pubdates: ["2008-07-14(纽约首映)",
"2008-07-18(美国)"
],
year: "2008",
images: {
small: "http://img1.doubanio.com/view/photo/s_ratio_poster/public/p462657443.webp",
large: "http://img1.doubanio.com/view/photo/s_ratio_poster/public/p462657443.webp",
medium: "http://img1.doubanio.com/view/photo/s_ratio_poster/public/p462657443.webp"
},
alt: "https://movie.douban.com/subject/1851857/",
id: "1851857"
},
title: "豆瓣电影 Top250"
}
如果我们使用 fromJson、toJson 来进行解析的话,就比较麻烦,并且还容易出错,因此我们使用一些工具来辅助进行 JSON 解析。
在线生成
首先,打开 JSON to Dart,如下图所示。
然后,我们将接口返回的 JSON 数据拷贝到输入框中,点击创建 Dart 类,然后右边就是生成好的 Dart 代码。
然后,创建一个 Dart 实体类,将上面生成的实体类代码拷贝过去即可。不过,我在使用此种方式进行 JSON 解析的时候,遇到一个问题,
Cannot generate dart code. Please check the project caveats.
如下图:
至于产生的原因我也不是非常清楚,有知道的可以解释下。
FlutterJsonBeanFactory 插件
除了上面的方式外,我们还可以使用 FlutterJsonBeanFactory 插件来辅助生成 Bean 类。
安装 FlutterJsonBeanFactory 插件很简单,以 Android Studio 为例,依次选择【Android Studio】->【Preferences…】->【Plugins】,然后搜索 FlutterJsonBeanFactory 插件安装即可,如下图所示。
安装成功之后重启 Android Studio 即可,重启之后在 new 的时候就会多一个【dart bean class File from Json】选项,如下图所示。
然后,在项目的 lib 目录下右键并选择【new】->【dart bean class File from JSON】来创建一个实体类,如下图。
然后,点击【Make】按钮就可以生成一个 dart 实体类,如下图。
可以发现,使用 JSON 转换插件来辅助开发,对于 Flutter 开发是非常方便的。除了 FlutterJsonBeanFactory 插件,另一款 FlutterJsonHelper 也可以完成 JSON 转换为 Entity 实体类的任务。
需要说明的是,生成实体类时,类名后面的 entity 是自动加上去的,可以在设置中配置自定义名称,如下图。
然后,我们就可以使用 dio 库或者 httpclient 来请求接口,并将它转换到 moviesentity 实体类上,如下所示:
// 获取电影列表
void getFilmList() async {Dio dio = new Dio();
Response response=await dio.get(hotMovies);
print('电影数据:'+response.toString());
Map userMap = json.decode(response.toString());
var movies = new MoviesEntity.fromJson(userMap);
}