JSONSerialization — فئة iOS مضمنة من إطار Foundation مصممة لتحويل JSON إلى كائنات Foundation والعكس. هذه API هي الآلية الأساسية للعمل مع JSON على منصات Apple دون مكتبات طرف ثالث، مع دعم تحليل القواميس والمصفوفات والأنواع البدائية. وفقًا لـ Apple Developer, 2024، يدعم JSONSerialization العمل مع Data والتدفقات وخيارات القراءة لمعالجة مرنة لبيانات JSON.
النقاط الرئيسية
JSONSerialization هي فئة من إطار Foundation متاحة على iOS وmacOS وtvOS وwatchOS. توفر طرقًا لتحويل بيانات JSON إلى كائنات Foundation (NSDictionary وNSArray وNSString وNSNumber) والعكس. ظهرت الفئة في iOS 5 وحتى تقديم Codable (Swift 4) بقيت الطريقة الرئيسية للعمل مع JSON على منصات Apple. على الرغم من عمرها، تظل JSONSerialization مطلوبة في مشاريع Objective-C القديمة وفي السيناريوهات التي تتطلب معالجة ديناميكية لـ JSON بدون مخطط نموذج ثابت.
على الرغم من ظهور Codable، تظل JSONSerialization مطلوبة في عدة سيناريوهات. هيكل JSON الديناميكي — عندما يتغير تنسيق الاستجابة أو يكون غير معروف مسبقًا — يتطلب الوصول إلى القواميس عبر المفاتيح، وهو أسهل من خلال JSONSerialization. تُستخدم الفئة أيضًا في مشاريع Objective-C حيث Codable غير متاح، وعند العمل مع التدفقات للتحليل المتزايد لملفات JSON الكبيرة. في الاختبارات والنماذج، تسمح isValidJSONObject وdata(withJSONObject:options:) بتوليد نماذج JSON بسرعة دون مكتبات طرف ثالث، مما يسرع التطوير والنمذجة الأولية.
import Foundation
// الهيكل الأساسي لاستخدام JSONSerialization
let jsonString = """
{
"id": 1,
"name": "John Doe",
"email": "john@example.com"
}
"""
guard let jsonData = jsonString.data(using: .utf8) else {
return
}
do {
let json = try JSONSerialization
.jsonObject(with: jsonData,
options: .mutableContainers)
print(json)
} catch {
print("خطأ تحليل JSON: \(error)")
}
JSONSerialization توفر أربع طرق رئيسية للعمل مع JSON. الطريقة الرئيسية هي jsonObject(with:options:)، التي تحول Data إلى كائنات Foundation. طريقة data(withJSONObject:options:) تقوم بالتسلسل العكسي. isValidJSONObject(_:) تتحقق مما إذا كان الكائن يمكن تسلسله. writeJSONObject(_:to:options:error:) تكتب JSON مباشرة إلى تدفق. لقراءة JSON من InputStream، توجد طريقة jsonObject(with:options:) التي تقبل تدفقًا بدلاً من Data، وهو مناسب عند التكامل مع طلبات الشبكة التي تعيد بيانات متدفقة.
طريقة jsonObject تقبل Data وتعيد Any — عادةً NSDictionary أو NSArray. للاستخدام الآمن، يتم تحويل النتيجة إلى النوع المتوقع من خلال التحويل الشرطي. طريقة data تقبل كائن Foundation وتعيد Data مع تمثيل JSON. يضيف الخيار .prettyPrinted تنسيقًا بمسافات بادئة لسهولة القراءة.
let jsonString = """
{
"products": [
{"id": 1, "name": "iPhone", "price": 999},
{"id": 2, "name": "iPad", "price": 799}
]
}
"""
let data = Data(jsonString.utf8)
if let json = try? JSONSerialization
.jsonObject(with: data) as? [String: Any],
let products = json["products"] as? [[String: Any]] {
for product in products {
if let name = product["name"] as? String {
print("المنتج: \(name)")
}
}
}
// التسلسل العكسي: كائن -> JSON
let outputDict: [String: Any] = ["status": "ok", "count": 42]
if let outputData = try? JSONSerialization
.data(withJSONObject: outputDict,
options: .prettyPrinted) {
String(data: outputData, encoding: .utf8)
}
التحليل الأساسي لقاموس بأنواع بدائية هي العملية الأكثر شيوعًا مع JSONSerialization. بعد استلام Data عبر URLSession، يستدعي المطور jsonObject ويحول النتيجة إلى النوع المتوقع. للمصفوفات من الكائنات، يُستخدم التحويل إلى [[String: Any]]، وبعد ذلك تتم معالجة كل عنصر في حلقة. هذا النهج مرن ولكنه يتطلب إدارة يدوية للأنواع.
واجهات API الحقيقية تعيد كائنات JSON متداخلة معقدة مع مصفوفات وتواريخ وحقول اختيارية. JSONSerialization تتعامل بشكل صحيح مع أي عمق تداخل، ولكن يجب على المطور تحويل كل مستوى إلى النوع المطلوب بشكل مستقل. لتبسيط هذه المهمة، توصي Apple باستخدام Codable للبيانات المنمطة وJSONSerialization فقط للهياكل الديناميكية.
// تحليل استجابة API
func parseUserResponse(data: Data) {
do {
guard let json = try JSONSerialization
.jsonObject(with: data) as? [String: Any]
else { return }
guard let userId = json["id"] as? Int,
let name = json["name"] as? String
else {
throw ParsingError.missingField
}
print("المستخدم: \(name) (المعرف: \(userId))")
} catch let error as ParsingError {
print("فشل التحليل: \(error)")
} catch {
print("خطأ غير متوقع: \(error)")
}
}
enum ParsingError: Error {
case missingField
case invalidType
}
JSONSerialization ترمي أخطاءً عند JSON غير صالح، أو عدم تطابق الأنواع، أو تجاوز عمق التداخل. تنتمي الأخطاء إلى نوع CocoaError وتحتوي على رمز يصف المشكلة. يجب على المطور معالجتها من خلال بنية do-catch، وإلا سيتعطل التطبيق. الأخطاء الأكثر شيوعًا هي: NSPropertyListReadCorruptError (JSON غير صالح) وNSPropertyListReadUnknownError. كل نوع خطأ يتطلب استراتيجية معالجة خاصة: للتنسيق غير الصالح، طلب إعادة إرسال البيانات، ولعدم تطابق الهيكل، تحديث نموذج التحليل.
JSON غير صالح — السبب الأكثر شيوعًا للفشل: فاصلة مفقودة، حرف إضافي، أو علامة اقتباس غير مُهربة تعطل التحليل بالكامل. النوع الثاني من الأخطاء هو عدم التطابق مع الهيكل المتوقع: على سبيل المثال، أعاد الخادم مصفوفة بدلاً من قاموس. JSONSerialization.fragmentsAllowed يسمح بقراءة JSON الذي جذره ليس قاموسًا أو مصفوفة بل قيمة بدائية. قد يواجه المطور أيضًا خطأ تجاوز عمق التداخل عندما يحتوي JSON على مستويات هرمية كثيرة جدًا.
JSONSerialization توفر عدة خيارات لتكوين التحليل. .mutableContainers يُرجع NSMutableDictionary وNSMutableArray بدلاً من الإصدارات غير القابلة للتغيير، وهو مفيد عند تعديل البيانات بعد التحليل. .mutableLeaves يجعل قيم السلاسل قابلة للتغيير. .fragmentsAllowed يسمح بـ JSON الذي جذره ليس كائنًا أو مصفوفة بل سلسلة أو رقم — مناسب للاستجابات API البسيطة. الخيارات .withoutEscapingSlashes و.sortedKeys متاحة لطريقة data(withJSONObject:options:)، للتحكم في تنسيق JSON المسلسل. تُمرر الخيارات كقناع بتات، مما يسمح بدمج عدة قيم عبر العامل | لتكوين تحليل مرن.
// معالجة أنواع مختلفة من الأخطاء
func safeParse(jsonData: Data) {
do {
let object = try JSONSerialization
.jsonObject(with: jsonData,
options: .fragmentsAllowed)
if let dictionary = object as? [String: Any] {
print("قاموس يحتوي على \(dictionary.count) مفاتيح")
} else if let array = object as? [Any] {
print("مصفوفة تحتوي على \(array.count) عناصر")
}
} catch CocoaError.propertyListReadCorrupt {
print("بيانات JSON تالفة")
} catch let error as CocoaError {
print("خطأ Cocoa: \(error)")
} catch {
print("خطأ غير معروف: \(error)")
}
}
// التحقق من صحة الكائن قبل التسلسل
let testObject: [String: Any] = ["key": "value", "nested": ["a": 1]]
if JSONSerialization.isValidJSONObject(testObject) {
print("كائن JSON صالح")
}
يعتمد أداء JSONSerialization على حجم البيانات وتكرار الاستدعاءات. للتحليل الفردي لاستجابة خادم صغيرة، الفرق طفيف، ولكن عند معالجة عشرات الميغابايت من JSON أو الاستدعاءات المتكررة في الحلقات، يجب مراعاة الحمل الإضافي لتحويل الأنواع. JSONSerialization يعمل بشكل متزامن في الخيط الحالي، لذلك للمستندات الكبيرة يُوصى بنقل التحليل إلى قائمة انتظار خلفية عبر DispatchQueue.global(). بدلاً من ذلك، يمكنك استخدام InputStream للمعالجة المتدفقة دون تحميل الملف بأكمله في الذاكرة، وهو أمر بالغ الأهمية للتطبيقات ذات الموارد المحدودة. لكتابة JSON إلى ملف أو تدفق شبكة، تسمح طريقة writeJSONObject(_:to:options:error:) بإرسال البيانات المسلسلة مباشرة إلى OutputStream دون إنشاء كائن Data وسيط، مما يقلل استهلاك الذاكرة عند العمل مع المستندات الكبيرة.
الأسئلة الشائعة
JSONSerialization هي فئة Foundation لتحويل بيانات JSON إلى كائنات Foundation (NSDictionary, NSArray) والعكس. تعمل على iOS وmacOS وtvOS وwatchOS دون مكتبات إضافية.
Codable هو بروتوكول Swift للتسلسل التلقائي المنمط الذي يُترجم إلى كود آمن بالأنواع. JSONSerialization يعمل مع أنواع ديناميكية Any ويتطلب تحويلًا يدويًا. Codable أفضل للمشاريع الجديدة، JSONSerialization لـ Objective-C والبيانات الديناميكية.
استخدم بنية do-catch عند استدعاء jsonObject. أخطاء JSONSerialization تنتمي إلى CocoaError. للتصحيح، تحقق من NSPropertyListReadCorruptError الذي يشير إلى تنسيق بيانات JSON غير صالح.
نعم، JSONSerialization يدعم أي عمق تداخل للقواميس والمصفوفات. يتم تحويل جميع الكائنات المتداخلة إلى أنواع Foundation المقابلة (NSDictionary, NSArray, NSString, NSNumber)، مع الحفاظ على هيكل JSON الأصلي.
JSONSerialization مناسب للهياكل JSON الديناميكية، في مشاريع Objective-C، عند العمل مع التدفقات، وللتحقق من صحة JSON عبر isValidJSONObject. للهياكل المنمطة ذات مخطط معروف، Codable أفضل.
الخلاصة
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.
اقرأ أيضًا