Flutter學(xué)習(xí)小計:實現(xiàn)json數(shù)據(jù)的解析

前言
最近Google開源的跨平臺移動開發(fā)框架Flutter非常火熱,推出了1.0的正式版,趁著熱度,我也是抽空粗略地學(xué)習(xí)了一下。目前網(wǎng)上Flutter相關(guān)的資料和開源項目也非常多了,在學(xué)習(xí)的過程中給了我很多幫助。因此,我想通過一系列文章記錄一下自己學(xué)習(xí)Flutter遇到的一些問題,既是對自身技術(shù)的鞏固,也方便日后即時查閱。

本文介紹一下Flutter中如何進行json數(shù)據(jù)的解析。在移動端開發(fā)中,請求服務(wù)端返回json數(shù)據(jù)并解析是一個很常見的使用場景。Android原生開發(fā)中,有GsonFormat這樣的神器,一鍵生成JavaBean,并利用Gson實現(xiàn)json數(shù)據(jù)和對象的轉(zhuǎn)化;在React Native中更是得益于直接使用javascript語言,無需對json對象進行解析便可以直接訪問屬性。那么在Flutter中如何實現(xiàn)對json數(shù)據(jù)的解析呢?
Flutter采用dart語言進行開發(fā),dart具有很多核心庫,其中dart:convert庫中內(nèi)置了json轉(zhuǎn)換器,可以實現(xiàn)將json數(shù)據(jù)轉(zhuǎn)換成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串的方法很簡單,直接調(diào)用json.decode()即可,但是由于json.decode()方法返回類型為dynamic,因此無法進行類型的檢查,編譯時不會報錯,容易使程序發(fā)生錯誤。采取的做法是像原生開發(fā)一樣,新建一個model實體類,將json轉(zhuǎn)為實體類對象。生成實體類的方法有以下兩種:

方法一.手寫實體類

一個簡單的實體類實例如下

class User{
  final String name;
  final String email;

  User(this.name,this.email);

  // 命名構(gòu)造函數(shù)
  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是一個命名構(gòu)造函數(shù),通過傳入的map構(gòu)造出實體類對象;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);
  // 將列表中的第一個對象轉(zhuǎn)換成User對象
  print(User.fromJson(list[0]).name);
  
  // 將對象序列化為json串
  // json.encode()會自動調(diào)用實體類中的toJson()
  String jsonText = json.encode(user);
  print(jsonText); 
}

這樣就完成了將json轉(zhuǎn)化成實體對象,步驟很簡單,但是還有一個問題是,真的每個實體類都要我們自己去手寫嗎,有沒有類似GsonFormat這種一鍵生成實體類的插件呢。當然是有的,之前從鴻洋大神推薦的Flutter學(xué)習(xí)資源中偶然發(fā)現(xiàn)了一個神奇的網(wǎng)站:
https://javiercbk.github.io/json_to_dart/

JSON To Dart.png

可以直接通過json生成實體類代碼,仿佛是發(fā)現(xiàn)了新大陸,不得不佩服開發(fā)出這些快捷工具的大神們,為后面學(xué)習(xí)的人鋪平了道路。網(wǎng)站的操作很簡單,一看就會。
最近偶然發(fā)現(xiàn)Android Studio也有了相關(guān)插件,我使用的是FlutterJsonBeanFactory,安裝過程我就不說了,裝好在目錄下右鍵依次選擇New、dart bean class File from JSON,之后會彈出一個窗口,填入json字符串和實體類名稱,就可以像GsonFormat那樣自動生成dart實體類文件啦。

需要注意的是默認情況生成的文件名和類名會加上entity后綴,可以從設(shè)置中進行配置,依次點擊File→Settings,從Tools下選擇FlutterJsonBeanFactory,修改model suffix即可。

方法二.通過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字段名對應(yīng)的屬性名,不是必須的
  @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
  • 持續(xù)生成
    在項目根目錄文件夾下運行
flutter packages pub run build_runner watch

兩者的區(qū)別是,一次性生成只執(zhí)行一次,后面每新建一個實體類都需要重新運行該命令;持續(xù)生成會在我們編寫代碼的過程中根據(jù)需要自動生成缺少的文件。
之后解析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);
}

這里關(guān)于實體類的生成我找到了做人要簡單這位大神寫的網(wǎng)頁工具,同樣是可以很方便地將json轉(zhuǎn)換成實體類代碼。

json_serializable實體類生成工具

生成代碼后點擊下載將實體類dart文件下載到本地,之后放到項目中,在項目根目錄運行上面提到的生成文件命令即可。
當然也可以通過自已定義模板編寫腳本來生成實體類文件,具體做法可以參考《Flutter實戰(zhàn)》

總結(jié)

Flutter中json的解析分為兩步:
1.通過json.decode()將json串轉(zhuǎn)換成dart對象(Map或List)
2.編寫實體類(兩種方法,手寫或自動生成),利用上一步得到的dart對象構(gòu)造出實體類對象
其實在實際的開發(fā)中,有可能并不需要第一步,這和服務(wù)端返回給我們的數(shù)據(jù)格式有關(guān)(響應(yīng)頭中的Content-Type),如果服務(wù)端直接返回給我們json格式(對應(yīng)Content-Type:application/json),我們可以直接從返回的響應(yīng)中獲取到dart對象,省去了第一步,直接轉(zhuǎn)化成實體類對象即可;如果服務(wù)端返回給我們的是純文本格式(對應(yīng)Content-Type:text/html,這里不一定是html,也有可能是xml等其他格式),則需要先將響應(yīng)的字符串轉(zhuǎn)換成dart對象。

參考資料

《Flutter實戰(zhàn)》Json轉(zhuǎn)Model
flutter json解析相關(guān) for json_serializable

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容