التسلسل وإلغاء التسلسل هما عمليتان أساسيتان لتحويل الكائنات إلى تنسيق للإرسال أو التخزين. في التطوير المحمول، تُستخدم هذه الآليات مع كل طلب شبكة، وحفظ الحالة، والتواصل بين العمليات. وفقاً لـ MDN Web Docs, 2024، لا يزال JSON التنسيق الأكثر شيوعاً للتسلسل في الويب والتطبيقات المحمولة، متجاوزاً XML و Protocol Buffers.
الخلاصة
التسلسل هو عملية تحويل كائن تطبيق إلى تنسيق مناسب للإرسال عبر الشبكة أو التخزين على القرص. يقوم إلغاء التسلسل بالتحويل العكسي، واستعادة الكائن من البيانات المستلمة. في التطوير المحمول، يُستخدم التسلسل في طلبات API، وحفظ حالة الشاشة، والتخزين المؤقت، ونقل البيانات عبر Intent أو Bundle.
أي تفاعل بين مكونات التطبيق أو بين التطبيق والخادم يتطلب تسلسلاً. واجهات API REST تنقل البيانات بتنسيق JSON أو XML، بينما يستخدم gRPC Protocol Buffers، ويستخدم التواصل داخل العملية على Android تقنية Parcelable. بدون التسلسل، من المستحيل تمرير كائن معقد عبر حدود العملية أو حفظه في قاعدة بيانات.
// المبدأ العام للتسلسل
data class User(
val id: Int,
val name: String,
val email: String
)
// التسلسل: كائن -> JSON
fun serializeUser(user: User): String {
return """{"id":${user.id},"name":"${user.name}","email":"${user.email}"}"""
}
// إلغاء التسلسل: JSON -> كائن
fun deserializeUser(json: String): User? {
// تحليل JSON إلى كائن
return Gson().fromJson(json, User::class.java)
}
| التنسيق | الحجم | السرعة | قابلية القراءة | الكتابة |
|---|---|---|---|---|
| JSON | متوسط | عالية | عالية | ديناميكية |
| XML | كبير | متوسطة | عالية | مخطط XSD |
| Protocol Buffers | صغير | عالية جداً | منخفضة | صارمة .proto |
| FlatBuffers | صغير | قصوى | منخفضة | صارمة .fbs |
JSON (JavaScript Object Notation) هو تنسيق نصي خفيف يعتمد على بناء جملة كائنات JavaScript. يدعم JSON السلاسل النصية والأرقام والقيم المنطقية والمصفوفات والكائنات المتداخلة، مما يغطي معظم سيناريوهات نقل البيانات في التطبيقات المحمولة. التنسيق مستقل عن المنصة: كل نظام بيئي يوفر أدوات مدمجة لتحليله.
يتفوق JSON بفضل بساطته وتعدد استخداماته. لا يحتاج المطور إلى مخطط للاستخدام الأساسي — يتم تحديد البنية ديناميكياً أثناء التحليل. قابلية قراءة التنسيق تبسط التصحيح والاختبار: يمكن عرض استجابة الخادم في أي أداة مطور. على كلتا المنصتين المحمولتين، تتم معالجة JSON بشكل أصلي دون الحاجة إلى مكتبات خارجية.
// Codable — التسلسل الأصلي لـ JSON في Swift
struct User: Codable {
let id: Int
let name: String
let email: String
}
let jsonString = """{"id":1,"name":"John","email":"john@test.com"}"""
let jsonData = Data(jsonString.utf8)
let decoder = JSONDecoder()
let user = try! decoder.decode(User.self, from: jsonData)
Protocol Buffers (protobuf) هو تنسيق تسلسل ثنائي طورته Google للأنظمة عالية الأداء. على عكس JSON، يتطلب protobuf مخططاً محدداً مسبقاً في ملف .proto، لكنه يوفر حجماً أصغر للبيانات وسرعة معالجة أعلى بكثير. يُستخدم التنسيق في gRPC و Firebase Firestore والخدمات الداخلية لـ Google.
يصف مخطط protobuf الرسائل بحقول مكتوبة،每個 منها برقم فريد. مجمّع protoc يُنشئ فئات بلغة الهدف تقوم بالتسلسل وإلغاء التسلسل تلقائياً. يدعم Protobuf تطور المخطط من خلال قواعد إضافة وإزالة الحقول دون فقدان التوافق مع الإصدارات السابقة.
// تعريف المخطط في user.proto
syntax = "proto3";
message User {
int32 id = 1;
string name = 2;
string email = 3;
repeated string roles = 4;
}
// الكود المُنشأ في Kotlin
val user = UserProto.User.newBuilder()
.setId(1)
.setName("John")
.setEmail("john@test.com")
.build()
val bytes: ByteArray = user.toByteArray()
XML (eXtensible Markup Language) هو تنسيق ببنية صلبة ودعم لمساحات الأسماء والتحقق عبر مخططات XSD. يخسر XML أمام JSON في الاكتناز وسرعة التحليل، لكنه يظل مطلوباً في تطوير Android لملفات التخطيط و AndroidManifest والموارد وتكوينات Gradle. على iOS، يُستخدم XML في ملفات plist وبعض الخدمات القديمة.
يوفر Android ثلاث طرق لتحليل XML: DOM (تحميل المستند بأكمله في الذاكرة)، و SAX (تحليل تدفقي يعتمد على الأحداث)، و XmlPullParser (نهج هجين). XmlPullParser هو الخيار الموصى به للأجهزة المحمولة، حيث يعمل بكفاءة مع الذاكرة المحدودة ويسمح بمعالجة المستند أثناء قراءته.
// XmlPullParser على Android
fun parseUserXml(inputStream: InputStream): User? {
val parser = Xml.newPullParser()
parser.setInput(inputStream, Xml.Encoding.UTF_8.name)
var id: Int? = null
var name: String? = null
var email: String? = null
while (parser.next() != XmlPullParser.END_DOCUMENT) {
if (parser.eventType == XmlPullParser.START_TAG
&& parser.name == "email") {
email = parser.nextText()
}
}
return User(id!!, name!!, email!!)
}
تقدم كل منصة أدواتها الخاصة للتسلسل. على iOS، الآلية الأساسية هي بروتوكول Codable مع JSONEncoder و JSONDecoder، بينما يستخدم Objective-C NSJSONSerialization. يستخدم Android مكتبات Gson و Moshi و kotlinx.serialization. لنقل البيانات بين العمليات، يستخدم Android Parcelable، بينما يستخدم iOS NSKeyedArchiver. تختار مشاريع Kotlin بشكل متزايد kotlinx.serialization — وهو حل من JetBrains يدعم تعدد المنصات ولا يعتمد على الانعكاس، حيث يُنشئ متسلسلات في وقت التجميع عبر مكوّن مترجم Kotlin.
يدعم Android آليتين للتسلسل لـ Intent و Bundle. Serializable هي آلية Java قياسية تستخدم الانعكاس، مما يؤدي إلى أداء منخفض. Parcelable هو بروتوكول خاص بنظام Android يتطلب تنفيذاً يدوياً لطريقي writeToParcel و createFromParcel، لكنه يعمل أسرع بعشرات المرات بفضل المعالجة المباشرة للبايتات.
// Parcelable على Android
@Parcelize
data class UserParcel(
val id: Int,
val name: String,
val email: String
) : Parcelable
// النقل عبر Intent
val intent = Intent(this, DetailActivity::class.java)
intent.putExtra("user", userParcel)
startActivity(intent)
على iOS، يُستخدم Codable مع تسلسل أولي إلى Data لنقل البيانات بين وحدات التحكم، بينما يُستخدم NSKeyedArchiver للتواصل بين العمليات، حيث يحول الكائنات إلى تنسيق Property List الثنائي. تفضل مشاريع SwiftUI الحديثة ترميز البيانات عبر JSONEncoder لنقلها بين وحدات التطبيق.
يمكن أن يؤدي إلغاء التسلسل غير الصحيح للبيانات غير الموثوقة إلى ثغرات أمنية. الهجمات عبر التسلسل تستغل طرق readObject المعاد تعريفها في Java أو أدوات إلغاء التسلسل غير الآمنة في المكتبات الخارجية. على Android، يجب تجنب Serializable للبيانات من مصادر غير موثوقة، واستخدام Parcelable أو التحقق اليدوي من جميع الحقول بعد إلغاء التسلسل. على iOS، JSONDecoder صارم افتراضياً مع الأنواع، لكن عند العمل مع JSONSerialization، يجب على المطورين التحقق من الأنواع عبر التحويل الشرطي.
عند اختيار تنسيق التسلسل، تؤخذ في الاعتبار متطلبات الأداء وحجم البيانات والتوافق. لواجهات API REST وهندسة الخدمات المصغرة، يظل JSON الخيار الأمثل — فهو مدعوم من جميع المنصات واللغات. للأنظمة عالية الحمل والتطبيقات المحمولة ذات النطاق الترددي المحدود، يُفضل Protocol Buffers الذي يوفر حجماً أصغر وسرعة إلغاء تسلسل أسرع. XML مبرر فقط في سيناريوهات التكوين وعند التكامل مع الأنظمة القديمة. في المشاريع الحديثة، يكتسب FlatBuffers شعبية — وهو تنسيق ثنائي بدون مرحلة إلغاء تسلسل، يُستخدم في محركات الألعاب والتطبيقات ذات زمن الوصول الأدنى. كل تنسيق له مجاله الخاص، والاختيار الصحيح يؤثر مباشرة على سرعة التطبيق وحجم حركة المرور المستهلكة.
الأسئلة الشائعة
التسلسل هو تغليف كائن تطبيق بتنسيق يمكن إرساله عبر الشبكة أو حفظه في ملف. تخيل أنك تلتقط صورة لشيء ما — الصورة هي التسلسل، واستعادة الشيء من الصورة هو إلغاء التسلسل.
JSON هو تنسيق نصي قابل للقراءة البشرية ولا يتطلب مخططاً. Protocol Buffers هو تنسيق ثنائي بمخطط إلزامي (.proto)، وحجم أصغر بكثير، وسرعة أعلى. Protobuf يُختار للأنظمة عالية الحمل، بينما JSON يُختار للتوافق الشامل.
يظل XML المعيار لملفات التكوين (AndroidManifest، موارد التخطيط)، والمستندات ذات التداخل المعقد، والأنظمة ذات التحقق الصارم عبر XSD. XML يُستخدم أيضاً في بروتوكولات SOAP والأنظمة القديمة التي تتطلب دعم مساحات الأسماء.
Codable هو بروتوكول Swift يجمع بين Encodable و Decodable للتسلسل وإلغاء التسلسل تلقائياً. يُنشئ المترجم تنفيذ طريقي encode(to:) و init(from:) لجميع خصائص الهيكل أو الفئة.
Parcelable يعمل أسرع بكثير من Serializable لأنه لا يستخدم الانعكاس ويكتب الحقول مباشرة إلى تدفق البايت. على الأجهزة الحديثة، يمكن أن يصل الفرق إلى تسريع بمقدار 10 أضعاف لصالح Parcelable.
الملخص
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.
اقرأ أيضًا