في بعض الأحيان ، يلزم تحويل 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 في مشروع Flutter وأضف الحزمة built_value إلى التبعيات :
...
built_value: ^7.1.0
وأيضا إضافة built_value_generator و build_runner حزم ل dev_dependencies . ستساعدك هذه الحزم في إنشاء الرموز المطلوبة.
تبعيات التنمية :
...
build_runner: ^1.10.2
built_value_generator: ^7.1.0
احفظ ملف pubspec.yaml وقم بتشغيل “ flutter pub get ” للحصول على جميع الحزم المطلوبة.
إنشاء build_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;
}
لذلك ، أنشأنا فئة مستخدم مجردة بسيطة مع حقل اسم واحد ، أشرنا إلى أن صنفنا جزء من 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
لاغية
أضف حقل اسم جديد إلى فئة المستخدم :
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".
ل جعل لقب اختياري، واستخداملاغية:
@nullable
String get surname;
أو تحتاج إلى إعطاء اللقب في كل مرة :
final user = User((b) => b
..name = 'Max'
..surname = 'Madov');
print(user);
المجموعة المبنية
دعنا نستخدم المصفوفات. ستساعدنا BuildList على هذا :
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);
تعداد
من الضروري تقييد الحقوق بحيث لا تأخذ أي قيم أخرى غير " قراءة " و " كتابة " و " حذف ". للقيام بذلك ، قم بإنشاء ملف جديد باسم 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 .
نضيف أيضًا سطرًا واحدًا إلى الفئة الصحيحة:
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();
يجب إضافة كل فئة مدمجة جديدة إلى 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 Code ، فإنني أوصي بتثبيت مقتطف يسمى Built Value Snippets وبعد ذلك يمكنك إنشاء كل هذا تلقائيًا. للقيام بذلك ، ابحث في السوق أو اتبع هذا الرابط .
بعد التثبيت ، اكتب " bv " في ملف Dart ويمكنك معرفة الخيارات الموجودة.
إذا كنت لا تريد أن يعرض Visual Studio Code ملفات " * .g.dart " التي تم إنشاؤها ، فأنت بحاجة إلى فتح الإعدادات والبحث عن الملفات: استبعاد ، ثم النقر فوق إضافة نمط وإضافة "** / *. g.dart ”.
ماذا بعد؟
للوهلة الأولى ، قد يبدو أن هذا القدر من الجهد لا يستحق كل هذا العناء ، ولكن إذا كان لديك الكثير من هذه الفئات ، فسيؤدي ذلك إلى تسهيل وتسريع العملية برمتها.
ملاحظة: سأكون سعيدًا جدًا وممتنًا لك إذا قمت بمشاركة طرقك ، والتي تجدها أكثر عملية وفعالية من الطريقة التي اقترحتها. حزم
مشروع GitHub
:
pub.dev/packages/built_value
pub.dev/packages/built_value_generator
pub.dev/packages/build_runner