1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
|
local rep = string.rep
local format = string.format
local gsub = string.gsub
local sub = string.sub
local sort = table.sort
local find = string.find
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(' ', 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
data = tostring(data)
-- 判断 inf -inf -nan(ind) 1.#INF -1.#INF -1.#IND
if find(data, '%a') then
data = '0'
end
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
|