Terkadang JSON dari API perlu diubah menjadi objek dan sebaiknya nilai yang tidak berubah. Pada Dart itu mungkin, tetapi membutuhkan banyak pengkodean untuk masing-masing objek. Untungnya, ada paket yang akan membantu Anda melakukan semua ini, dan dalam artikel ini saya akan memberi tahu Anda tentang metode ini.
Tujuan kami:
1. Serialisasi
final user = User.fromJson({"name": "Maks"});
final json = user.toJson();
2. Gunakan sebagai nilai
final user1 = User.fromJson({"name": "Maks"});
final user2 = User((b) => b..name='Maks');
if (user1 == user2) print(' ');
3. Kekekalan
user.name = 'Alex'; //
final newUser = user.rebuild((b) => b..name='Alex'); //
Instal paket
Buka file pubspec.yaml di proyek Flutter kami dan tambahkan paket built_value ke dependensi :
...
built_value: ^7.1.0
Dan juga tambahkan paket built_value_generator dan build_runner ke dev_dependencies . Paket-paket ini akan membantu Anda menghasilkan kode yang diperlukan.
dev_dependencies :
...
build_runner: ^1.10.2
built_value_generator: ^7.1.0
Simpan file pubspec.yaml dan jalankan " flutter pub get " untuk mendapatkan semua paket yang diperlukan.
Buat nilai_bangun
Mari buat kelas sederhana untuk melihat cara kerjanya.
Buat file baru 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;
}
Jadi, kami membuat kelas Pengguna abstrak sederhana dengan satu bidang nama , menunjukkan bahwa kelas kami adalah bagian dari user.g.dart dan implementasi utamanya ada di sana, termasuk UserBuilder . Untuk membuat file ini secara otomatis, Anda perlu menjalankannya di baris perintah:
flutter packages pub run build_runner watch
atau
flutter packages pub run build_runner build
Kami mulai dengan jam tangan agar tidak memulai ulang setiap kali ada perubahan di kelas.
Setelah itu, kita melihat bahwa file user.g.dart baru telah muncul . Anda dapat melihat apa yang ada di dalamnya dan berapa banyak waktu yang akan kami hemat dengan mengotomatiskan proses ini. Ketika kami menambahkan lebih banyak bidang dan serialisasi, file ini akan menjadi lebih besar.
Mari kita periksa apa yang kita dapatkan:
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
nullable
Tambahkan bidang nama keluarga baru ke kelas Pengguna :
abstract class User implements Built<User, UserBuilder> {
String get name;
String get surname;
...
}
Jika Anda mencoba seperti ini:
final user = User((b) => b..name = 'Max');
Kemudian kami mendapatkan kesalahan:
Tried to construct class "User" with null field "surname".
Untuk membuat nama keluarga opsional, gunakannullable:
@nullable
String get surname;
atau Anda perlu memberikan nama belakang setiap kali :
final user = User((b) => b
..name = 'Max'
..surname = 'Madov');
print(user);
Koleksi yang Dibangun
Mari gunakan array. BuiltList akan membantu kami untuk ini :
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);
Enum
Perlu untuk membatasi hak agar tidak mengambil nilai lain selain ' read ', ' write ' dan ' delete '. Untuk melakukan ini, buat file baru bernama right.dart buat EnumClass baru :
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);
}
Pengguna:
@nullable
BuiltList<Right> get rights;
Sekarang hak hanya menerima jenis yang Tepat :
final user = User((b) => b
..name = 'Max'
..rights.addAll([Right.read, Right.write]));
print(user);
Serialisasi
Agar objek ini dapat dengan mudah diubah menjadi JSON dan kembali, kita perlu menambahkan beberapa metode lagi ke kelas kita:
...
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;
}
Pada prinsipnya, ini cukup untuk serialisasi:
static Serializer<User> get serializer => _$userSerializer;
Tetapi untuk kenyamanan, mari tambahkan metode toJson dan fromJson .
Kami juga menambahkan satu baris ke kelas Kanan:
import 'package:built_value/serializer.dart';
,,,
class Right extends EnumClass {
...
static Serializer<Right> get serializer => _$rightSerializer;
}
Dan Anda perlu membuat file lain bernama 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();
Setiap kelas Built baru perlu ditambahkan ke @SerializersFor ([ ... ]) agar serialisasi berfungsi seperti yang diharapkan .
Sekarang kami dapat memeriksa apa yang kami dapatkan:
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
Mari kita ubah nilainya:
final user3 = user.rebuild((b) => b
..surname = "Madov"
..rights.replace([Right.read]));
print(user3);
Selain itu
Alhasil, akan ada yang mengatakan masih perlu menulis cukup banyak. Tetapi jika Anda menggunakan Visual Studio Code, saya sarankan menginstal potongan bernama Built Value Snippets dan kemudian Anda dapat menghasilkan semua ini secara otomatis. Untuk melakukan ini, telusuri Marketplace atau ikuti tautan ini .
Setelah instalasi, tulis " bv " di file Dart dan Anda dapat melihat opsi apa yang ada.
Jika Anda tidak ingin Visual Studio Code menampilkan file " * .g.dart " yang dihasilkan , Anda perlu membuka Pengaturan dan mencari Files: Exclude , lalu klik Add Pattern dan tambahkan "** / *. g.dart ”.
Apa berikutnya?
Pada pandangan pertama, tampaknya usaha yang begitu banyak tidak sepadan, tetapi jika Anda memiliki banyak kelas seperti itu, ini akan sangat memudahkan dan mempercepat keseluruhan proses.
NB Saya akan sangat senang dan berterima kasih kepada Anda jika Anda mau membagikan metode Anda, yang menurut Anda lebih praktis dan lebih efektif daripada yang saya usulkan. Paket
proyek GitHub
:
pub.dev/packages/built_value
pub.dev/packages/built_value_generator
pub.dev/packages/build_runner