عام JSONDecoder

في الوقت الحالي ، الغالبية العظمى من تطبيقات الهاتف المحمول هي خادم عميل. في كل مكان هناك التحميل والمزامنة وإرسال الأحداث والطريقة الرئيسية للتفاعل مع الخادم هي تبادل البيانات باستخدام تنسيق json.


مفتاح فك التشفير


لدى المؤسسة آليتان لتسلسل البيانات الميتة. قديم NSJsonSerialization والجديد هو Codable . يحتوي الأخير في قائمة المزايا على شيء رائع فيه مثل الإنشاء التلقائي للمفاتيح لبيانات json استنادًا إلى هيكل (أو فئة) يقوم بتنفيذ Codable ( Encodable ، Decodable ) Decodable لفك تشفير البيانات.


يبدو أن كل شيء على ما يرام ، يمكنك استخدامه والتمتع به ، ولكن الواقع ليس بهذه البساطة.
في كثير من الأحيان على الخادم يمكنك رؤية json من النموذج:


 {"topLevelObject": { "underlyingObject": 1 }, "Error": { "ErrorCode": 400, "ErrorDescription": "SomeDescription" } } 

هذا مثال على الحياة الواقعية تقريبًا من أحد خوادم المشروع.


بالنسبة لفئة JsonDecoder ، JsonDecoder تحديد العمل باستخدام مفاتيح snake_case ، ولكن ماذا لو كان لدينا UpperCamelCase أو dash-snake-case أو حتى hodgepodge عام ، لكننا لا نريد كتابة المفاتيح يدويًا؟


لحسن الحظ ، قدمت Apple القدرة على تكوين تعيين المفاتيح قبل CodingKeys مع بنية JSONDecoder.KeyDecodingStrategy باستخدام JSONDecoder.KeyDecodingStrategy . سوف نستفيد من هذا.


أولاً ، قم بإنشاء بنية تنفذ بروتوكول CodingKey ، لأنه لا يوجد في المكتبة القياسية:


  struct AnyCodingKey: CodingKey { var stringValue: String var intValue: Int? init(_ base: CodingKey) { self.init(stringValue: base.stringValue, intValue: base.intValue) } init(stringValue: String) { self.stringValue = stringValue } init(intValue: Int) { self.stringValue = "\(intValue)" self.intValue = intValue } init(stringValue: String, intValue: Int?) { self.stringValue = stringValue self.intValue = intValue } } 

ثم من الضروري معالجة كل حالة على حدة من مفاتيحنا بشكل منفصل. أهمها:
snake_case ، dash-snake-case ، lowerCamelCase و UpperCamelCase. تحقق ، تشغيل ، كل شيء يعمل.


ثم نواجه مشكلة متوقعة إلى حد ما: الاختصارات في camelCase'ah (تذكر id ، ID ، ID ). لجعلها تعمل ، تحتاج إلى تحويلها بشكل صحيح وإدخال قاعدة - يتم تحويل الاختصارات إلى camelCase ، مع الاحتفاظ بالأحرف الكبيرة الأولى فقط وسوف يتحول myABBRKey إلى myAbbrKey .


هذا الحل يعمل بشكل رائع لمجموعة من الحالات المتعددة.


ملاحظة: سيتم توفير التطبيق. إستراتيجية فك تشفير المفتاح .custom .


 static func convertToProperLowerCamelCase(keys: [CodingKey]) -> CodingKey { guard let last = keys.last else { assertionFailure() return AnyCodingKey(stringValue: "") } if let fromUpper = convertFromUpperCamelCase(initial: last.stringValue) { return AnyCodingKey(stringValue: fromUpper) } else if let fromSnake = convertFromSnakeCase(initial: last.stringValue) { return AnyCodingKey(stringValue: fromSnake) } else { return AnyCodingKey(last) } } 

تاريخ فك التشفير


المشكلة الروتينية التالية هي طريقة تمرير التواريخ. هناك الكثير من الخدمات المصغرة على الخادم ، وهناك عدد أقل قليلاً من الأوامر ، ولكن أيضًا هناك كمية مناسبة ، ونتيجة لذلك ، نواجه مجموعة من تنسيقات التواريخ مثل "نعم ، أنا أستخدم المعيار". بالإضافة إلى ذلك ، شخص ما يمر التواريخ في سلسلة ، شخص ما في وقت العصر. نتيجةً لذلك ، لدينا مرة أخرى مجموعة من مجموعات فاصل فاصل الأعداد الزمنية لمنطقة السلسلة ، DateDecoder في iOS ويتطلب تنسيق تاريخ صارم. الحل هنا بسيط ، فقط من خلال البحث نبحث عن علامات على تنسيق معين ودمجها ، والحصول على النتيجة اللازمة. لقد غطت هذه التنسيقات حالاتي بنجاح وبشكل كامل.


ملاحظة: هذا مُهيئ DateFormatter مخصص. في شكل مجموعة فقط لتنسيق المنسق.


 static let onlyDate = DateFormatter(format: "yyyy-MM-dd") static let full = DateFormatter(format: "yyyy-MM-dd'T'HH:mm:ss.SSSx") static let noWMS = DateFormatter(format: "yyyy-MM-dd'T'HH:mm:ssZ") static let noWTZ = DateFormatter(format: "yyyy-MM-dd'T'HH:mm:ss.SSS") static let noWMSnoWTZ = DateFormatter(format: "yyyy-MM-dd'T'HH:mm:ss") 

نحن نعلق هذا على وحدة فك JSONDecoder.DateDecodingStrategy باستخدام JSONDecoder.DateDecodingStrategy على وحدة فك ترميز تعالج أي شيء تقريبًا JSONDecoder.DateDecodingStrategy إلى تنسيق سهل الهضم بالنسبة لنا.


اختبارات الأداء


تم إجراء اختبارات لسلاسل json بحجم 7944 بايت.


convertFromSnakeCase استراتيجيةاستراتيجية anyCodingKey
مطلق0.001700.00210
قريب81٪100٪

كما نرى ، فإن Decoder المخصصة أبطأ بنسبة 20٪ بسبب التحقق الإلزامي لكل مفتاح في json للحاجة إلى التحويل. ومع ذلك ، يعد هذا رسمًا Codable لعدم الاضطرار إلى تسجيل مفاتيح هياكل البيانات بشكل صريح من خلال تطبيق Codable . يتم تقليل عدد لوحات الغلايات بدرجة كبيرة في المشروع مع إضافة وحدة فك التشفير هذه. هل يجب أن أستخدمه لتوفير وقت مطور البرامج ، لكن مع تدهور الأداء؟ الأمر متروك لك.


رمز عينة كاملة في مكتبة جيثب


المادة الانجليزية

Source: https://habr.com/ru/post/ar449870/


All Articles