Flutter Json自動逆シーケンス化-json_serializable v1.5.1|掘金技術徴文

17927 ワード

前言
Googleがflutterのような新しい高性能クロスプラットフォーム(Android,ios)の急速な開発フレームワークを発表した後、業界の多くの開発者に注目された.私はflutterに触れた後、これは確かに良いものだと気づきました.いいものはもちろんみんなと分かち合いますよね.
今日皆さんと分かち合うのはJsonの逆シーケンス化の実現です.appをする学生はこのような問題に直面すると信じています.サーバーにデータを要求すると、サーバーはjson文字列を返すことが多いです.データをより柔軟に使用するには、json文字列をオブジェクトに変換する必要があります.flutterはjson to Mapのみを提供しているためです.手書き逆シーケンス化は大規模なプロジェクトで極めて不安定であり,解析に失敗しやすい.そこで今日はflutterチームおすすめjsonをご紹介しますserializableは自動的に逆シーケンス化されます.
何を学ぶの?
  • flutterでjsonオブジェクト
  • をどのように解析するか
  • 自動生成ツールを使用してコード
  • を生成する方法
  • データをテストする方法
  • json逆シーケンス化の開始
    ステップ1:mockデータの作成
    実際の開発では、以前のコードを変更する可能性があります.コード機能が複雑で、十分な量がある場合は、新しく追加したコードが前に書いたコードに影響しないことを保証するために、ユニットテストを使用する必要があります.サーバのデータは常に変化するので、最初のステップはもちろん私たちのmockデータを作成します.
    ここではGITHUB/HackerNewsのデータを使用しています(github.com/HackerNews/…)
    abstract class JsonString{
      static final String mockdata = ''' {
      "by" : "dhouston",
      "descendants" : 71,
      "id" : 8863,
      "kids" : [ 8952, 9224, 8917, 8884, 8887, 8943, 8869, 8958, 9005, 9671, 8940, 9067, 8908, 9055, 8865, 8881, 8872, 8873, 8955, 10403, 8903, 8928, 9125, 8998, 8901, 8902, 8907, 8894, 8878, 8870, 8980, 8934, 8876 ],
      "score" : 111,
      "time" : 1175714200,
      "title" : "My YC app: Dropbox - Throw away your USB drive",
      "type" : "story",
      "url" : "http://www.getdropbox.com/u/2/screencast.html"
    }''';
    }
    

    ステップ2:依存の追加
    pubspec.yamlに次の依存を追加
    dependencies:
      # Your other regular dependencies here
      json_annotation: ^1.2.0
    
    dev_dependencies:
      # Your other dev_dependencies here
      build_runner: ^0.10.2
      json_serializable: ^1.5.1
    

    ここでは、「json_annotation」「build_runner」「json_serializable」の3つの依存を追加する必要があります.
    yamlプロファイルはインデントに厳しいので、次のbuild_runnerとjson_serializableはflutterとtest平級、flutterに書かないでください.testがインデントすると、この2つがflutter_とみなされます.testのサブセットディレクトリ!
    多くの友达がこの一歩で問題にぶつかったので、ここにソースコードを貼ってください.
    ステップ3:jsonに基づいてエンティティクラスを作成する
    ここでは上のjsonデータに基づいてdartのエンティティクラスを書きました
    class Data{
      final String by;
      final int descendants;
      final int id;
      final List<int> kids;
      final int score;
      final int time;
      final String title;
      final String type;
      final String url;
    
      Data({this.by, this.descendants, this.id, this.kids, this.score, this.time,
        this.title, this.type, this.url});
    }
    

    ここではdart構文糖を用いて構造関数を作成した.具体的には(www.dartlang.org/guides/lang...)を参照してください.
    ステップ4:エンティティクラスファイルの関連付け
    生成ファイルをエンティティクラスに関連付ける必要があります.
    import 'package:json_annotation/json_annotation.dart';
    
    part 'data.g.dart';
    
    @JsonSerializable()
    class Data {
      final String by;
      final int descendants;
      final int id;
      final List<int> kids;
      final int score;
      final int time;
      final String title;
      final String type;
      @JsonKey(nullable: false)
      final String url;
    
      Data({this.by, this.descendants, this.id, this.kids, this.score, this.time,
        this.title, this.type, this.url});
    

    dataを書き終わったばかりです.g.dartの報告が間違っています.これは正常です.解析ファイルが生成されていないので
  • エンティティクラスファイルに生成ファイルを見つけるにはpart'dataが必要です.g.dart'.

  • ステップ5:Json解析ファイルの生成
    当当当...!ここからがメインイベント!!
    JsonSerializableを使用してコードを生成するには、コードを生成するエンティティクラスの前に注記@JsonSerializable()を追加する必要がありますが、この注記を使用するにはjson_を導入する必要があります.annotation/json_annotation.dartというかばん.
    import 'package:json_annotation/json_annotation.dart';
    
    @JsonSerializable()
    class Data{
      final String by;
      final int descendants;
      final int id;
      final List<int> kids;
      final int score;
      final int time;
      final String title;
      final String type;
      final String url;
    
      Data({this.by, this.descendants, this.id, this.kids, this.score, this.time,
        this.title, this.type, this.url});
    }
    

    ここで、flutter符号化仕様dartファイル名を小文字に統一することで、多くの問題を回避できることに注意してください.OKこれでエンティティクラスの作成が完了します.
    では、問題が発生しました.コードをどのように生成すればいいのでしょうか.
    さっき追加したbuildを覚えています.runnerの依存か、この時私たちはそれを助ける必要があります.
    build_runner
    build_runnerはdartチームが提供するdartコードファイルを生成する外部パッケージです.
    現在のプロジェクトのディレクトリの下でflutter packages pub run build_runner buildを実行します.
    実行に成功したら、このエンティティクラスの下に新しいファイルを見つけることができます.
    このdata.g.dartはbuild_runnerがJsonSerializableから生成したjson解析ファイル.この生成されたdartファイルを見てみましょう
    // GENERATED CODE - DO NOT MODIFY BY HAND
    
    part of 'data.dart';
    
    // **************************************************************************
    // JsonSerializableGenerator
    // **************************************************************************
    
    Data _$DataFromJson(Map<String, dynamic> json) {
      return Data(
          by: json['by'] as String,
          descendants: json['descendants'] as int,
          id: json['id'] as int,
          kids: (json['kids'] as List)?.map((e) => e as int)?.toList(),
          score: json['score'] as int,
          time: json['time'] as int,
          title: json['title'] as String,
          type: json['type'] as String,
          url: json['url'] as String);
    }
    
    Map<String, dynamic> _$DataToJson(Data instance) => <String, dynamic>{
          'by': instance.by,
          'descendants': instance.descendants,
          'id': instance.id,
          'kids': instance.kids,
          'score': instance.score,
          'time': instance.time,
          'title': instance.title,
          'type': instance.type,
          'url': instance.url
        };
    
    

    皆さん、このコードの一番上のコメント「//GENERATED CODE-DO NOT MODIFY BY HAND」に注意してください.決して手書きでファイルを生成しないでください.ハハハハ.
    このコードは、エンティティクラスライブラリのpartを生成し、古いバージョンのpartに抽象エンティティクラスのmixinがあり、dartではmixinベースの継承を使用して単一継承の限界を解決します.
    新しいバージョンでは、fromJsonとtoJsonの2つの方法が主張されています.彼らは何ができるのか、名前から推測できると信じています.
    【パーティーに興味のある方は参考にしてくださいhttps://juejin.im/post/5b601f40e51d4519575a5036#heading-8 Dart|dartライブラリのインポートと分割を簡単に分析します.
    mixinに興味のある学生は(www.dartlang.org/guides/lang...)mixinに関する知識をもっと知ることができます.
  • _$DataFromJson:map:Mapを受信し、このMapの値を必要なエンティティクラスオブジェクトにマッピングします.この方法を使用して、jsonデータが格納されているmapを必要なエンティティクラスオブジェクトに変換することができます.
  • _$DataToJson:このメソッドを呼び出したオブジェクトをフィールドに直接マップします.

  • どちらもプライベートメソッドであり、partは2つのファイルに役割ドメインとネーミングスペースを共有させるため、生成されたメソッドを外部に露出する必要があります.
    次に、エンティティクラスに戻ってfromJsonメソッドとtoJsonメソッドを追加します.
    import 'package:json_annotation/json_annotation.dart';
    
    @JsonSerializable()
    class Data{
      final String by;
      final int descendants;
      final int id;
      final List<int> kids;
      final int score;
      final int time;
      final String title;
      final String type;
      final String url;
    
      Data({this.by, this.descendants, this.id, this.kids, this.score, this.time,
        this.title, this.type, this.url});
    //    
      factory Data.fromJson(Map<String, dynamic> json) => _$DataFromJson(json);
    //   
      Map<String, dynamic> toJson() => _$DataToJson(this);
    }
    
  • は工場の構造方法データを提供する.ファイルを生成するDataFromJsonメソッドを実際に呼び出すfromJson.
  • は、生成ファイルの_$を実際に呼び出すtoJson()シーケンス化オブジェクトの方法を提供する.DataToJson()メソッドは、呼び出されたオブジェクトを解析してMapを生成します.

  • これでJson逆シーケンス化の作業が完了!
    ステップ6:JSON逆シーケンス化
    私たちはさっきMapto Dartを実現しましたが、必要なのはjson to dartです.この時、dartが持っているdart:convertが私たちを助けてくれる必要があります.
    dart:convert
    dart:convertはdartが異なるデータ表現間を変換するためのエンコーダとデコーダを提供し、JSONとUTF-8を解析することができる.
    すなわち,jsonデータをdart:convertを用いてMapに変換する必要があり,Mapを介してdartオブジェクトに変換できる.
    使用方法
    Map<String ,dynamic> map = json.decode("jsondata");
    

    jsonStringをmapに解析する方法を知ったら、jsonをエンティティオブジェクトに直接変換することができます.
    変換方法
        Data data = Data.fromJson(json.decode('jsondata'));
    

    ステップ7:ユニットテストの作成
    flutterは私たちにユニットテストを提供してくれました.その利点は、コードの正確性を検証するためにプログラム全体を走る必要がなく、毎回1つのユニットテストファイルだけを走ることです.また、ユニットテストを書く習慣を身につけた後、開発過程で迅速に正確な位置決めミスを保証し、新しく追加されたコードが古いコードを破壊してプロジェクトの崩壊を引き起こすことを避けることができる.アプリケーションが起動するたびに、プロジェクトが正しく動作することを確認するために、ユニットテストを1回実行します.実際の開発で使用すべきmockデータは、テストデータのソースとして使用されます.
    使用方法:runというテストファイルを右クリック
    import 'dart:convert';
    
    import 'package:flutter_test/flutter_test.dart';
    import 'package:wmkids/data/mockdata.dart';
    import 'package:wmkids/data/data.dart';
    
    void main(){
      group('jsonparse test', (){
        test('mockdata test', (){
          Data data1 = Data.fromJson(json.decode(JsonString.mockdata));
          expect(data1.url, 'http://www.getdropbox.com/u/2/screencast.html');
        });
      });
    }
    

    最初のステップで作成したmockデータを用いてjsonのurlを検証し,このユニットテストを正しく解析すれば合格する.
    ここのgroupはテストのセットで、1つのgroupに複数のtestが私たちのコードが正しいかどうかを検証することができます.
    expect(data1,data2);私たちのdata 1とdata 2の値が等しいかどうかをチェックし、同じであればテストに合格します.もし違うならどこが違うか教えてくれます.
    常用シーン特殊処理方法
    オブジェクトネストシーンでのjson解析
    jsonではネスト情報がよく用いられ,dartファイルに解析する際にオブジェクトネストに解析する必要がある.このようなシーンでは、作成手順を調整する必要があります.オブジェクトに依存関係があるため、親が解析に成功することを保証するには、エンティティクラスを作成するときにファクトリメソッドを持参する必要があります.
    エラーが発生した場合に正常であることを示し、ファイルを生成します.
    カスタムフィールド
    JsonKeyカスタムパラメータでコメントし、パラメータをカスタマイズして各フィールドをカスタマイズできます.たとえば、フィールドが空であることを許可するかどうか.ここでは、JsonKeyのデフォルトで空のjsonフィールドは追加されません.
    例:
    ここでjsonは「-」をフィールド名として使用し、dartではアルファベット数の下線のみを変数名として許可します.だから私たちはそれを特別に処理しなければなりません.@JsonKey(name=「Nicehash−NHeavy」)を用いてmapを解析した.
    その後、ファイルを生成します.
    生成ファイルはmap中のNicehashCNHeavyをNicehash−NHeavyに置き換えたことが分かった.
    汎用状況
    githubソースリファレンス
    github.com/Vadaski/Vad…
    最後に書く
    以上がFlutter Json自動逆シーケンス化のすべての内容で、文章に間違いがあれば皆さんの大牛指摘を歓迎します!汎用的な問題についてもっと良い解決策があればコメントエリアで教えてほしいです^-^.
    その後、私は一連のflutter干物を更新します.好きなら、私に注目したり、好評を与えたりしてもいいですよ.もっとダイナミックに更新します.
    0から1:私のFlutter技術実践|掘金技術募集、募集活動が進行中