Flutter开发之JSON解析
对于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); }