diff options
Diffstat (limited to 'src/json/encode.lua')
-rw-r--r-- | src/json/encode.lua | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/src/json/encode.lua b/src/json/encode.lua new file mode 100644 index 00000000..135a51a1 --- /dev/null +++ b/src/json/encode.lua @@ -0,0 +1,128 @@ +local rep = string.rep +local format = string.format +local gsub = string.gsub +local sub = string.sub +local sort = table.sort +local tostring = tostring +local getmetatable = debug.getmetatable +local type = type +local next = next +local ipairs = ipairs + +local index +local lines +local n = -1 +local tabs = {} + +local esc_map = { + ['\\'] = '\\\\', + ['\r'] = '\\r', + ['\n'] = '\\n', + ['\t'] = '\\t', + ['"'] = '\\"', +} + +local function encode(data, key) + n = n + 1 + if not tabs[n] then + tabs[n] = rep('\t', n) + end + local tp = type(data) + if tp == 'table' then + if not data[1] and next(data) then + -- 认为这个是哈希表 + if key then + index=index+1;lines[index] = tabs[n] .. '"' .. gsub(key, '[\\\r\n\t"]', esc_map) .. '" : {\n' + else + index=index+1;lines[index] = tabs[n] .. '{\n' + end + local meta = getmetatable(data) + local sep + if meta and meta.__pairs then + for k, v in meta.__pairs(data), data do + if encode(v, k) then + index=index+1;lines[index] = ',\n' + sep = true + end + end + else + local list = {} + local i = 0 + for k in next, data do + i=i+1;list[i] = k + end + sort(list) + for j = 1, i do + local k = list[j] + if encode(data[k], k) then + index=index+1;lines[index] = ',\n' + sep = true + end + end + end + if sep then + lines[index] = '\n' + end + index=index+1;lines[index] = tabs[n] .. '}' + else + -- 认为这个是数组 + if key then + index=index+1;lines[index] = tabs[n] .. '"' .. gsub(key, '[\\\r\n\t"]', esc_map) .. '" : [\n' + else + index=index+1;lines[index] = tabs[n] .. '[\n' + end + local sep + for k, v in pairs(data) do + if encode(v) then + index=index+1;lines[index] = ',\n' + sep = true + end + end + if sep then + lines[index] = '\n' + end + index=index+1;lines[index] = tabs[n] .. ']' + end + elseif tp == 'number' then + if key then + index=index+1;lines[index] = tabs[n] .. '"' .. gsub(key, '[\\\r\n\t"]', esc_map) .. '" : ' .. data + else + index=index+1;lines[index] = tabs[n] .. data + end + elseif tp == 'boolean' then + if key then + index=index+1;lines[index] = tabs[n] .. '"' .. gsub(key, '[\\\r\n\t"]', esc_map) .. '" : ' .. tostring(data) + else + index=index+1;lines[index] = tabs[n] .. tostring(data) + end + elseif tp == 'nil' then + if key then + index=index+1;lines[index] = tabs[n] .. '"' .. gsub(key, '[\\\r\n\t"]', esc_map) .. '" : null' + else + index=index+1;lines[index] = tabs[n] .. 'null' + end + elseif tp == 'string' then + local str = gsub(data, '[\\\r\n\t"]', esc_map) + if key then + index=index+1;lines[index] = tabs[n] .. '"' .. gsub(key, '[\\\r\n\t"]', esc_map) .. '" : "' .. str .. '"' + else + index=index+1;lines[index] = tabs[n] .. '"' .. str .. '"' + end + else + n = n - 1 + return false + end + n = n - 1 + return true +end + +local function json(t) + lines = {} + index = 0 + + encode(t) + + return table.concat(lines) +end + +return json |