The simplest algorithm to differentiate between arrays/non-arrays is this one:
local function is_array(t)
local i = 0
for _ in pairs(t) do
i = i + 1
if t[i] == nil then return false end
end
return true
end
Explanation here: http://ericjmritz.name/2014/02/26/lua-is_array/
That said, you will still have issues with empty tables - are they "arrays" or "hashes"?
For the particular case of serializing json, what I do is marking arrays with a field in their metatable.
-- use this when deserializing
local function mark_as_array(t)
setmetatable(t, {__isarray = true})
end
-- use this when serializing
local function is_array(t)
local mt = getmetatable(t)
return mt.__isarray
end