Anomalia da biblioteca json do Corona SDK

Olá pessoal. Não é segredo para ninguém que o uso do json em seus projetos no Corona SDK pode tornar algumas coisas bastante convenientes. Eu encontrei uma anomalia interessante ao trabalhar com a biblioteca, que, como a prática demonstrou, não é um erro, mas um recurso que você deve conhecer e estar preparado. Vamos considerar tudo em detalhes.

1. Descrição do problema


Suponha que tenhamos uma matriz Lua que se parece com isso:

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

Se você tem tudo normal com a compreensão do idioma, essa matriz é apresentada como mostrado abaixo, com pouca gordura devido às circunstâncias - TÃO POSSÍVEL:

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

Se você decidir converter essa matriz para json, a saída fornecerá algo assim (é claro, não esqueceremos de conectar a biblioteca json):

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

Como você pode ver, o json também sabe sobre a existência desse tipo de registro simplificado, no qual, se os elementos da matriz forem seqüenciais, eles não serão explicitamente numerados, e isso é maravilhoso, pois costumamos usar o json em nossos projetos para o protocolo de rede ou para salvar em um arquivo, e o tamanho extra é completamente inexistente. para o que.

Agora vamos tentar converter o dreno novamente em uma tabela Lua e exibir seu conteúdo, prestando atenção nos tipos de dados das chaves:

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

Como você pode ver, o resultado é mais do que o esperado, a tabela ar na entrada corresponde totalmente à tabela ar2 na saída. Agora, seguindo os 2 pontos anteriores, mas ao mesmo tempo haverá uma matriz na qual há uma sequência interrompida na matriz, digamos que adicionamos a chave 6 (ignorando 5) com o valor 'wtf'. Nós estamos quebrando.

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

Como você pode ver, tudo ficou ótimo novamente, já que json.encode esperava essa captura e, em vez de uma chave 5 inexistente inserida nula e tudo terminou com sucesso, não pararemos por aí e adicionaremos outra chave 777 com o valor 1 à matriz, provavelmente esperamos que a tabela é convertida da mesma maneira e incluirá 770 null - essa certamente não é a melhor opção, pois ocupará muito mais espaço, mas simplesmente não há outra maneira no json para criar um análogo completo dessa tabela lua, pois a chave não está no json pode ser claramente vlen como um número. Nós olhamos o que aconteceu.

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

Como você pode ver, o codificador foi para o outro lado e converteu todas as chaves com o número do tipo de valor em string. Não é segredo que esse recurso pode e levará a erros (se você não o conhece) ou a muletas usando transformações explícitas de número de toneladas / rotação ao trabalhar com esta tabela; em qualquer caso, isso não trará muito prazer. Considere como lidar com isso.

2. resolvendo o problema


Para resolver esse problema, você pode escrever uma função que inicializará todas as matrizes em que o problema surgiu; em seguida, no código, você terá que se lembrar constantemente desse problema e aplicar essa função em qualquer lugar; essa é uma maneira normal, mas não a melhor; portanto, existe o plano B Redefina a implementação da função json.decode para que todas as áreas problemáticas sejam convertidas automaticamente e esta solução funcione tanto no primeiro aninhamento na matriz transferida quanto em anexos mais profundos. Redefiniremos o valor da função logo após conectar a biblioteca json ao projeto. A seguinte implementação está disponível:

 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 

Agora tente executar a operação anterior novamente:

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

Como você pode ver, tudo funcionou e a matriz manteve sua estrutura anterior. Por fim, quero acrescentar que, se por algum motivo você precisar evitar essa conversão, a nova opção de implementação json.decode oferecerá suporte a um segundo parâmetro opcional que desativará a conversão.

Tchau pessoal!

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


All Articles