1. 程式人生 > >Flutter 聯網和JSON轉換成Bean

Flutter 聯網和JSON轉換成Bean

Flutter 聯網和JSON轉換成Bean

Flutter的聯網分為HttpClient和dio兩種。HttpClient是dart io中的HttpClient發起的請求,但HttpClient本身功能較弱,很多常用功能都不支援。dart io官網文件.
dio是一個強大的Dart Http請求庫,支援Restful API、FormData、攔截器、請求取消、Cookie管理、檔案上傳/下載、超時等…dio github地址.
JSON型別資料的轉換分為兩種:手動序列化和反序列化 dart:convert和通過程式碼生成自動序列化和反序列化json_serializable。
手動JSON序列化是指使使用dart:convert中內建的JSON解碼器。它將原始JSON字串傳遞給JSON.decode() 方法,然後在返回的Map<String, dynamic>中查詢所需的值。 它沒有外部依賴或其它的設定,對於小專案很方便。
當您的專案變大時,手動編寫序列化邏輯可能變得難以管理且容易出錯。如果您在訪問未提供的JSON欄位時輸入了一個錯誤的欄位,則您的程式碼將會在執行時會引發錯誤。

HttpClient和dart convert序列化資料

String url = "https://httpbin.org/ip";
    var httpClient = HttpClient();
    String result;
    try {
     var request =  await httpClient.getUrl(Uri.parse(url));
     var response = await request.close();
     if(response.statusCode == HttpStatus.ok){
       var jsonStr =
await response.transform(utf8.decoder).join(); var date = json.decode(jsonStr); result = date['origin']; }else{ result = 'Error getting IP address:\nHttp status ${response.statusCode}'; } }catch(Exception){ result = 'Failed getting IP address'; }

這段程式碼用的是HttpClient和內連序列化JSON.
下面介紹。在模型類中序列化JSON:
1.先建立一個IpBean用於接收返回的資料

class IpBean{
  String origin;
  IpBean({this.origin});
  IpBean.fromJson(Map<String, dynamic> json)
      : origin = json['origin'];
  
  Map<String, dynamic> toJson() =>
      {
        'origin': origin,
      };
}

2.進行序列化:

 var jsonStr = await response.transform(utf8.decoder).join();
 IpBean ipBean = new IpBean.fromJson(ipMap);

3.反序列化:

       String ipStr = json.encode(ipBean);

這個地方可以檢視Flutter 中文官網地址.

dio請求庫和json_serializable序列化資料

1.匯入請求庫

dependencies:
 flutter:
    sdk: flutter
  json_annotation: ^1.2.0 
  dio: ^1.0.6
  dev_dependencies:
  flutter_test:
    sdk: flutter
  build_runner: ^1.1.1
  json_serializable: ^1.3.0

匯入這四個庫就可以開始愉快的聯網請求了

2.建立build.yaml檔案。
在專案的根目錄下新建一個build.yaml的檔案用於構件專案時自動生成程式碼:
build.yaml程式碼

targets:
  $default:
    builders:
      json_serializable:
        options:
          # Options configure how source code is generated for every
          # `@JsonSerializable`-annotated class in the package.
          #
          # The default value for each is listed.
          #
          # For usage information, reference the corresponding field in
          # `JsonSerializableGenerator`.
          any_map: false
          checked: false
          create_factory: true
          create_to_json: true
          disallow_unrecognized_keys: false
          explicit_to_json: false
          field_rename: none
          generate_to_json_function: true
          include_if_null: true
          nullable: true
          use_wrappers: false

3.準備好要序列化的Bean類

import 'package:json_annotation/json_annotation.dart';
part 'ImageBean.g.dart';

@JsonSerializable()
class ImageBean{

  ImageBean(this.url);
  String url;
  factory ImageBean.fromJson(Map<String, dynamic> json) => _$ImageBeanFromJson(json);
  Map<String, dynamic> toJson() => _$ImageBeanToJson(this);
}


part 'ImageListBean.g.dart';
@JsonSerializable()
class ImageListBean{

  ImageListBean(this.results,this.error);
  List<ImageBean> results;
  bool error;
  factory ImageListBean.fromJson(Map<String, dynamic> json) => _$ImageListBeanFromJson(json);
  Map<String, dynamic> toJson() => _$ImageListBeanToJson(this);
}

第一次建立類時,您會看到與下圖類似的錯誤
在這裡插入圖片描述
這些錯誤是完全正常的,這是因為model類的生成程式碼還不存在。為了解決這個問題,我們必須執行程式碼生成器來為我們生成序列化模板。

4.執行程式碼生成器
有兩種執行程式碼生成器的方法:
一次性生成
通過在我們的專案根目錄下執行flutter packages pub run build_runner build,我們可以在需要時為我們的model生成json序列化程式碼。 這觸發了一次性構建,它通過我們的原始檔,挑選相關的併為它們生成必要的序列化程式碼。
雖然這非常方便,但如果我們不需要每次在model類中進行更改時都要手動執行構建命令的話會更好。

持續生成
使用_watcher_可以使我們的原始碼生成的過程更加方便。它會監視我們專案中檔案的變化,並在需要時自動構建必要的檔案。我們可以通過flutter packages pub run
build_runner watch在專案根目錄下執行來啟動_watcher_。
只需啟動一次觀察器,然後並讓它在後臺執行,這是安全的。
5.使用dio庫傳送網路請求,並完成序列化

print("------------------------開始請求--------------------------------------");
    Dio dio = Dio();
    dio.options.baseUrl = "https://gank.io/";
    dio.options.connectTimeout = 5000;
    dio.options.receiveTimeout = 5000;
    dio.options.responseType = ResponseType.JSON;
    dio.options.path = "/api/data/福利/10/1";
    dio.options.headers = {
      'user-agent': 'dio',
      'from': "dio"
    };
    Response response = await dio.get("/api/data/福利/10/1");
    var data = response.data;
    print(data);
    print(response.data is String);
    ImageListBean image = ImageListBean.fromJson(data);
    print("------------------------請求結束---------------------------------------");

這樣就完成了一次網路請求。
參考文件
Flutter中文網 在Flutter中發起HTTP網路請求
Flutter中文網 JSON和序列化