مكتبة كورونا SDK json شذوذ

مرحبا بالجميع. لا يخفى على أحد أن استخدام json في مشاريعك على Corona SDK يمكن أن يجعل بعض الأشياء مريحة تمامًا. لقد وجدت حالة شاذة مثيرة للاهتمام عند العمل مع المكتبة ، والتي أظهرت الممارسة أنها ليست خطأ على الإطلاق ، بل هي ميزة يجب أن تعرفها وتكون مستعدًا لها. دعونا نفكر في كل شيء بالتفصيل.

1. وصف المشكلة


افترض أن لدينا صفيف Lua يبدو كالتالي:

ar = {23,45,56,'weer'} 

إذا كان لديك كل شيء طبيعي مع فهم للغة ، فسيتم تقديم هذه المجموعة لك كما هو موضح أدناه ، فقط قليل الدسم بسبب الظروف - لذلك ممكن:

 ar = {[1] = 23,[2] = 45,[3] = 56,[4] = 'weer'} 

إذا قررت تحويل هذا الصفيف إلى json ، فسوف يمنحك الإخراج شيئًا كهذا (بالطبع ، لن ننسى ربط مكتبة json):

 ar = {[1] = 23,[2] = 45,[3] = 56,[4] = 'weer'} json = require "json" local str = json.encode(ar) print(str)--> [23,45,56,"weer"] 

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

الآن دعنا نحاول تحويل التصريف مرة أخرى إلى جدول Lua وعرض محتوياته ، مع الانتباه إلى أنواع بيانات المفاتيح:

 local str = '[23,45,56,"weer"]' local ar2 = json.decode(str) for k,v in pairs(ar2)do print(k,type(k),v) end --[[ 1 number 23 2 number 45 3 number 56 4 number weer ]] 

كما ترى ، تكون النتيجة أكثر من المتوقع ، يتوافق الجدول ar عند الإدخال تمامًا مع الجدول ar2 عند الإخراج. الآن ، بعد النقطتين السابقتين ، ولكن في نفس الوقت سيكون هناك صفيف يوجد فيه تسلسل متقطع في الصفيف ، دعنا نقول أننا أضفنا المفتاح 6 (تجاوز 5) بالقيمة 'wtf'. نحن نكسر.

 json = require "json" ar = {23,45,56,'weer',[6] = 'wtf'} local str = json.encode(ar) print(str)-->[23,45,56,"weer",null,"wtf"] local t = json.decode(str) for k,v in pairs(t)do print(k,type(k),v) end --[[ 1 number 23 2 number 45 3 number 56 4 number weer 6 number wtf ]] 

كما ترى ، تحول كل شيء بشكل رائع مرة أخرى ، حيث توقع json.encode هذا الالتقاط وبدلاً من وجود مفتاح 5 غير موجود تم إدخاله فارغًا وانتهى كل ذلك بنجاح ، لن نتوقف عند هذا الحد ونضيف 777 مفتاحًا آخر بقيمة 1 إلى الصفيف ، على الأرجح نتوقع أن الجدول تم تحويله بنفس الطريقة وسيتضمن 770 null - وهذا بالتأكيد ليس الخيار الأفضل لأنه سيأخذ مساحة أكبر بكثير ، ولكن ببساطة لا توجد طريقة أخرى في json لإنشاء تناظرية كاملة لجدول lua هذا لأن المفتاح ليس في json قد يكون من الواضح vlen كرقم. نحن ننظر إلى ما حدث.

 json = require "json" ar = {23,45,56,'weer',[6] = 'wtf',[777] = 1} local str = json.encode(ar) print(str)-->{"1":23,"2":45,"3":56,"4":"weer","6":"wtf","777":1} local t = json.decode(str) for k,v in pairs(t)do print(k,type(k),v) end --[[ 1 string 23 777 string 1 3 string 56 2 string 45 4 string weer 6 string wtf ]] 

كما ترون ، ذهب المشفر في الاتجاه الآخر وقام بتحويل جميع المفاتيح برقم نوع القيمة إلى سلسلة. ليس سرا أن مثل هذه الميزة يمكن أن تؤدي إلى أخطاء (إذا كنت لا تعرف عنها) ، أو إلى عكازات باستخدام تحويلات صريحة / أوتار عند العمل مع هذا الجدول ، على أي حال ، لن يجلب هذا الكثير من المتعة. فكر في كيفية التعامل مع هذا.

2. حل المشكلة


من أجل حل هذه المشكلة ، يمكنك كتابة دالة تهيئ جميع الصفائف التي نشأت فيها المشكلة ، ثم في الكود سيكون عليك تذكر هذه المشكلة باستمرار وتطبيق هذه الوظيفة في كل مكان ، وهذه طريقة عادية ، ولكنها ليست الأفضل ، وبالتالي هناك خطة B أعد تعريف تنفيذ وظيفة json.decode بحيث يتم تحويل جميع مناطق المشكلة تلقائيًا وسيعمل هذا الحل على التعشيش الأول في الصفيف الذي تم تمريره وعلى المرفقات الأعمق. سنقوم بإعادة تعريف قيمة الوظيفة مباشرة بعد توصيل مكتبة json بالمشروع. التنفيذ التالي متاح:

 json = require "json" local jd = json.decode--   local norm_ar json.decode = function(ar,not_convert)--  local res = jd(ar) --     --    norm_ar = function(root) local res = {} --  for k,v in pairs(root)do res[k] = v end --   for k,v in pairs(res) do if type(k) == 'string' and--  string.match(tostring(k),'%D') == nil then--    -- string -> number root[tonumber(k)] = root[k] root[k] = nil--   end --      if type(v) == 'table' then norm_ar(v) end end return root end --   not_convert    return not_convert and res or norm_ar(res) end 

حاول الآن تنفيذ العملية السابقة مرة أخرى:

 ar = {23,45,56,'weer',[6] = 'wtf',[777] = 1} local str = json.encode(ar) print(str)-->{"1":23,"2":45,"3":56,"4":"weer","6":"wtf","777":1} local t = json.decode(str) for k,v in pairs(t)do print(k,type(k),v) end --[[ 1 number 23 2 number 45 3 number 56 4 number weer 6 number wtf 777 number 1 --]] 

كما ترون ، عمل كل شيء واحتفظ الصفيف بهيكله السابق. أخيرًا ، أريد أن أضيف أنه إذا احتجت لسبب ما لتجنب هذا التحويل ، فإن خيار تنفيذ json.decode الجديد يدعم معلمة اختيارية ثانية ستعطل التحويل.

وداعا للجميع!

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


All Articles