APIからのJSONをオブジェクトに、できれば不変の値に変換する必要がある場合があります。Dartでは可能ですが、オブジェクトごとに多くのコーディングが必要です。幸いなことに、これをすべて行うのに役立つパッケージがあります。この記事では、この方法について説明します。
私たちの目標:
1。シリアル化
final user = User.fromJson({"name": "Maks"});
final json = user.toJson();
2.値として使用
final user1 = User.fromJson({"name": "Maks"});
final user2 = User((b) => b..name='Maks');
if (user1 == user2) print(' ');
3.不変性
user.name = 'Alex'; //
final newUser = user.rebuild((b) => b..name='Alex'); //
パッケージをインストールする
開きpubspec.yamlのファイルを、当社のフラッタプロジェクトに追加し、built_valueのパッケージをへの依存関係:
...
built_value: ^7.1.0
そしてまた、追加built_value_generatorとbuild_runnerパッケージにdev_dependencies。これらのパッケージは、必要なコードを生成するのに役立ちます。
dev_dependencies:
...
build_runner: ^1.10.2
built_value_generator: ^7.1.0
pubspec.yaml ファイルを保存し、「flutter pub get」を実行して、必要なすべてのパッケージを取得します。
built_valueを作成します
これがどのように機能するかを確認するために、簡単なクラスを作成してみましょう。
新しいファイルuser.dartを作成します。
import 'package:built_value/built_value.dart';
part 'user.g.dart';
abstract class User implements Built<User, UserBuilder> {
String get name;
User._();
factory User([void Function(UserBuilder) updates]) = _$User;
}
そのため、1つの名前フィールドを持つ単純な抽象Userクラスを作成しました。これは、クラスがuser.g.dartの一部であり、UserBuilderを含むメインの実装がそこにあることを示しています。このファイルを自動的に作成するには、コマンドラインでこれを実行する必要があります。
flutter packages pub run build_runner watch
または
flutter packages pub run build_runner build
クラスで何かが変わるたびに再起動しないように 、ウォッチから始めます。
その後、新しいuser.g.dartファイルが表示されたことがわかります。このプロセスを自動化することで、内部の内容と節約できる時間を確認できます。フィールドとシリアル化を追加すると、このファイルはさらに大きくなります。
私たちが得たものを確認しましょう:
final user = User((b) => b..name = "Max");
print(user);
print(user == User((b) => b..name = "Max")); // true
print(user == User((b) => b..name = "Alex")); // false
null可能
Userクラスに 新しい姓フィールドを追加します。
abstract class User implements Built<User, UserBuilder> {
String get name;
String get surname;
...
}
あなたがこのようにしようとすると:
final user = User((b) => b..name = 'Max');
次に、エラーが発生します。
Tried to construct class "User" with null field "surname".
するに作る姓オプション、使用null可能:
@nullable
String get surname;
または、毎回姓を付ける必要があります:
final user = User((b) => b
..name = 'Max'
..surname = 'Madov');
print(user);
構築されたコレクション
配列を使ってみましょう。BuiltListはこれに役立ちます:
import 'package:built_collection/built_collection.dart';
...
abstract class User implements Built<User, UserBuilder> {
...
@nullable
BuiltList<String> get rights;
...
final user = User((b) => b
..name = 'Max'
..rights.addAll(['read', 'write']));
print(user);
列挙
' read '、 ' write '、および ' delete '以外の値をとらないように権限を制限する必要があります。これを行うには、right.dartという名前の新しいファイルを作成します。新しいEnumClassを作成します。
import 'package:built_collection/built_collection.dart';
import 'package:built_value/built_value.dart';
part 'right.g.dart';
class Right extends EnumClass {
static const Right read = _$read;
static const Right write = _$write;
static const Right delete = _$delete;
const Right._(String name) : super(name);
static BuiltSet<Right> get values => _$rightValues;
static Right valueOf(String name) => _$rightValueOf(name);
}
ユーザー:
@nullable
BuiltList<Right> get rights;
現在、権利は権利タイプのみを受け入れます:
final user = User((b) => b
..name = 'Max'
..rights.addAll([Right.read, Right.write]));
print(user);
シリアル化
これらのオブジェクトを簡単にJSONに変換したり元に戻したりできるように、クラスにさらにいくつかのメソッドを追加する必要があります。
...
import 'package:built_value/serializer.dart';
import 'serializers.dart';
...
abstract class User implements Built<User, UserBuilder> {
...
Map<String, dynamic> toJson() => serializers.serializeWith(User.serializer, this);
static User fromJson(Map<String, dynamic> json) =>
serializers.deserializeWith(User.serializer, json);
static Serializer<User> get serializer => _$userSerializer;
}
原則として、これはシリアル化には十分です。
static Serializer<User> get serializer => _$userSerializer;
ただし、便宜上、toJsonメソッドとfromJsonメソッドを追加しましょう。
また、Rightクラスに1行追加します。
import 'package:built_value/serializer.dart';
,,,
class Right extends EnumClass {
...
static Serializer<Right> get serializer => _$rightSerializer;
}
そして、serializers.dartという別のファイルを作成する必要があります。
import 'package:built_collection/built_collection.dart';
import 'package:built_value/serializer.dart';
import 'package:built_value/standard_json_plugin.dart';
import 'package:built_value_demo/right.dart';
import 'package:built_value_demo/user.dart';
part 'serializers.g.dart';
@SerializersFor([Right, User])
final Serializers serializers =
(_$serializers.toBuilder()..addPlugin(StandardJsonPlugin())).build();
シリアル化が期待どおりに機能するためには、 新しいBuiltクラスをそれぞれ@SerializersFor([ ... ])に追加する必要があります。
これで、取得したものを確認できます。
final user = User.fromJson({
"name": "Max",
"rights": ["read", "write"]
});
print(user);
print(user.toJson());
final user2 = User((b) => b
..name = 'Max'
..rights.addAll([Right.read, Right.write]));
print(user == user2); // true
値を変更しましょう:
final user3 = user.rebuild((b) => b
..surname = "Madov"
..rights.replace([Right.read]));
print(user3);
さらに
その結果、まだかなりたくさん書く必要があると言う人がいるでしょう。ただし、Visual Studioコードを使用する場合は、Built Value Snippetsというスニペットをインストールすることをお勧めします。そうすれば、これらすべてを自動的に生成できます。これを行うには、マーケットプレイスを検索するか、このリンクをたどってください。
インストール後、Dartファイルに「bv」と書き込むと、どのオプションが存在するかを確認できます。生成された「* .g.dart」ファイルをVisualStudio Codeに表示さ
せたくない場合は、[設定]を開いて[ファイル] :[除外]を探し、[パターンの追加]をクリックして「** / *。g.dart」。
次は何ですか?
一見、それほど努力する価値はないように思われるかもしれませんが、そのようなクラスがたくさんある場合、これはプロセス全体を大幅に促進し、スピードアップします。
PS私が提案した方法よりも実用的で効果的な方法を共有していただければ、とてもうれしく思います。
GitHubプロジェクト
パッケージ:
pub.dev/packages/built_value
pub.dev/packages/built_value_generator
pub.dev/packages/build_runner