Corona SDK json anomali perpustakaan

Halo semuanya. Bukan rahasia bagi siapa pun bahwa menggunakan json dalam proyek Anda di Corona SDK dapat membuat beberapa hal cukup nyaman. Saya menemukan satu anomali menarik ketika bekerja dengan perpustakaan, yang telah ditunjukkan oleh praktik sama sekali bukan kesalahan, melainkan fitur yang harus Anda waspadai dan siapkan. Mari kita pertimbangkan semuanya secara rinci.

1. Deskripsi masalah


Misalkan kita memiliki array Lua yang terlihat seperti ini:

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

Jika Anda memiliki semuanya normal dengan pemahaman bahasa, array ini disajikan kepada Anda seperti yang ditunjukkan di bawah ini, hanya rendah lemak karena keadaan - JADI MUNGKIN:

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

Jika Anda memutuskan untuk mengubah array ini menjadi json, maka outputnya akan memberi Anda sesuatu seperti ini (tentu saja, kami tidak akan lupa untuk menghubungkan pustaka json):

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

Seperti yang Anda lihat, json juga tahu tentang keberadaan catatan yang disederhanakan ini, di mana jika elemen-elemen array berjalan secara berurutan, mereka tidak akan diberi nomor secara eksplisit, dan ini luar biasa karena kita sering menggunakan json dalam proyek-proyek kami untuk protokol jaringan atau untuk menyimpan ke file, dan ukuran ekstra sama sekali tidak ada untuk apa.

Sekarang mari kita coba konversi saluran kembali ke tabel Lua dan tampilkan isinya, sambil memperhatikan tipe data kunci:

 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 ]] 

Seperti yang Anda lihat, hasilnya lebih dari yang diharapkan, tabel ar pada input sepenuhnya sesuai dengan tabel ar2 pada output. Sekarang, mengikuti 2 poin sebelumnya, tetapi pada saat yang sama akan ada sebuah array di mana ada urutan terputus dalam array, katakanlah kita menambahkan kunci 6 (memintas 5) dengan nilai 'wtf'. Kami bangkrut.

 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 ]] 

Seperti yang Anda lihat, semuanya menjadi hebat lagi, karena json.encode mengharapkan tangkapan ini dan alih-alih tidak ada 5 kunci yang dimasukkan nol dan ini semua berakhir dengan sukses, kami tidak akan berhenti di situ dan menambahkan kunci 777 lainnya dengan nilai 1 ke array, kemungkinan besar kami harapkan bahwa tabel dikonversi dengan cara yang sama dan akan menyertakan 770 null - ini jelas bukan pilihan terbaik karena akan memakan lebih banyak ruang, tetapi tidak ada cara lain di json untuk membuat analog penuh dari tabel lua ini karena kuncinya bukan di json mungkin jelas vlen sebagai angka. Kami melihat apa yang terjadi.

 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 ]] 

Seperti yang Anda lihat, encoder pergi ke arah lain dan mengkonversi semua kunci dengan nomor tipe nilai ke string. Bukan rahasia lagi bahwa fitur seperti itu dapat dan akan menyebabkan kesalahan (jika Anda tidak mengetahuinya), atau ke kruk menggunakan transformasi tonumber / tostring eksplisit ketika bekerja dengan tabel ini, dalam hal apa pun, ini tidak akan membawa banyak kesenangan. Pertimbangkan cara menangani ini.

2. menyelesaikan masalah


Untuk mengatasi masalah ini, Anda dapat menulis fungsi yang akan menginisialisasi semua array di mana masalah muncul, maka dalam kode Anda harus terus-menerus mengingat masalah ini dan menerapkan fungsi ini di mana-mana, ini adalah cara yang normal, tetapi bukan yang terbaik, dan oleh karena itu ada rencana B Definisikan kembali implementasi fungsi json.decode sehingga semua area masalah dikonversi secara otomatis dan solusi ini akan berfungsi baik pada nesting pertama dalam array yang diteruskan dan pada lampiran yang lebih dalam. Kami akan melakukan redefinisi nilai fungsi segera setelah kami menghubungkan json library ke proyek. Implementasi berikut tersedia:

 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 

Sekarang coba lakukan operasi sebelumnya lagi:

 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 --]] 

Seperti yang Anda lihat, semuanya berfungsi dan array mempertahankan struktur sebelumnya. Terakhir, saya ingin menambahkan bahwa jika karena alasan tertentu Anda perlu menghindari konversi ini, opsi implementasi json.decode baru mendukung parameter opsional kedua yang akan menonaktifkan konversi.

Selamat tinggal semuanya!

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


All Articles