Json.lua 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506
  1. --[[
  2. JSON Encoder and Parser for Lua 5.1
  3. Copyright ?2007 Shaun Brown (http://www.chipmunkav.com).
  4. All Rights Reserved.
  5. Permission is hereby granted, free of charge, to any person
  6. obtaining a copy of this software to deal in the Software without
  7. restriction, including without limitation the rights to use,
  8. copy, modify, merge, publish, distribute, sublicense, and/or
  9. sell copies of the Software, and to permit persons to whom the
  10. Software is furnished to do so, subject to the following conditions:
  11. The above copyright notice and this permission notice shall be
  12. included in all copies or substantial portions of the Software.
  13. If you find this software useful please give www.chipmunkav.com a mention.
  14. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  15. EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  16. OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  17. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
  18. ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
  19. CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  20. CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  21. Usage:
  22. -- Lua script:
  23. local t = {
  24. ["name1"] = "value1",
  25. ["name2"] = {1, false, true, 23.54, "a \021 string"},
  26. name3 = Json.Null()
  27. }
  28. local json = Json.Encode (t)
  29. print (json)
  30. --> {"name1":"value1","name3":null,"name2":[1,false,true,23.54,"a \u0015 string"]}
  31. local t = Json.Decode(json)
  32. print(t.name2[4])
  33. --> 23.54
  34. Notes:
  35. 1) Encodable Lua types: string, number, boolean, table, nil
  36. 2) Use Json.Null() to insert a null value into a Json object
  37. 3) All control chars are encoded to \uXXXX format eg "\021" encodes to "\u0015"
  38. 4) All Json \uXXXX chars are decoded to chars (0-255 byte range only)
  39. 5) Json single line // and /* */ block comments are discarded during decoding
  40. 6) Numerically indexed Lua arrays are encoded to Json Lists eg [1,2,3]
  41. 7) Lua dictionary tables are converted to Json objects eg {"one":1,"two":2}
  42. 8) Json nulls are decoded to Lua nil and treated by Lua in the normal way
  43. --]]
  44. local error = error
  45. local tonumber = tonumber
  46. local tostring = tostring
  47. local type = type
  48. local setmetatable = setmetatable
  49. local pairs = pairs
  50. local ipairs = ipairs
  51. local assert = assert
  52. --local Chipmunk = Chipmunk
  53. --module("Json")
  54. --module(..., package.seeall)
  55. local StringBuilder = {
  56. buffer = {}
  57. }
  58. function StringBuilder:New()
  59. local o = {}
  60. setmetatable(o, self)
  61. self.__index = self
  62. o.buffer = {}
  63. return o
  64. end
  65. function StringBuilder:Append(s)
  66. self.buffer[#self.buffer+1] = s
  67. end
  68. function StringBuilder:ToString()
  69. return table.concat(self.buffer)
  70. end
  71. local JsonWriter = {
  72. backslashes = {
  73. ['\b'] = "\\b",
  74. ['\t'] = "\\t",
  75. ['\n'] = "\\n",
  76. ['\f'] = "\\f",
  77. ['\r'] = "\\r",
  78. ['"'] = "\\\"",
  79. ['\\'] = "\\\\",
  80. ['/'] = "\\/"
  81. }
  82. }
  83. function JsonWriter:New()
  84. local o = {}
  85. o.writer = StringBuilder:New()
  86. setmetatable(o, self)
  87. self.__index = self
  88. return o
  89. end
  90. function JsonWriter:Append(s)
  91. self.writer:Append(s)
  92. end
  93. function JsonWriter:ToString()
  94. return self.writer:ToString()
  95. end
  96. function JsonWriter:Write(o)
  97. local t = type(o)
  98. if t == "nil" then
  99. self:WriteNil()
  100. elseif t == "boolean" then
  101. self:WriteString(o)
  102. elseif t == "number" then
  103. self:WriteString(o)
  104. elseif t == "string" then
  105. self:ParseString(o)
  106. elseif t == "table" then
  107. self:WriteTable(o)
  108. elseif t == "function" then
  109. self:WriteFunction(o)
  110. elseif t == "thread" then
  111. self:WriteError(o)
  112. elseif t == "userdata" then
  113. self:WriteError(o)
  114. end
  115. end
  116. function JsonWriter:WriteNil()
  117. self:Append("null")
  118. end
  119. function JsonWriter:WriteString(o)
  120. self:Append(tostring(o))
  121. end
  122. function JsonWriter:ParseString(s)
  123. self:Append('"')
  124. self:Append(string.gsub(s, "[%z%c\\\"/]", function(n)
  125. local c = self.backslashes[n]
  126. if c then return c end
  127. return string.format("\\u%.4X", string.byte(n))
  128. end))
  129. self:Append('"')
  130. end
  131. function JsonWriter:IsArray(t)
  132. local count = 0
  133. for k in pairs(t) do
  134. count = count + 1
  135. if k ~= count then
  136. return false, '{', '}'
  137. end
  138. end
  139. return true, '[', ']', count
  140. end
  141. function JsonWriter:WriteTable(t)
  142. local ba, st, et, n = self:IsArray(t)
  143. self:Append(st)
  144. if ba then
  145. for i = 1, n do
  146. self:Write(t[i])
  147. if i < n then
  148. self:Append(',')
  149. end
  150. end
  151. else
  152. local first = true;
  153. for k, v in pairs(t) do
  154. if not first then
  155. self:Append(',')
  156. end
  157. first = false;
  158. self:ParseString(k)
  159. self:Append(':')
  160. self:Write(v)
  161. end
  162. end
  163. self:Append(et)
  164. end
  165. function JsonWriter:WriteError(o)
  166. error(string.format(
  167. "Encoding of %s unsupported",
  168. tostring(o)))
  169. end
  170. function JsonWriter:WriteFunction(o)
  171. if o == Null then
  172. self:WriteNil()
  173. else
  174. self:WriteError(o)
  175. end
  176. end
  177. local StringReader = {
  178. s = "",
  179. i = 0
  180. }
  181. function StringReader:New(s)
  182. local o = {}
  183. setmetatable(o, self)
  184. self.__index = self
  185. o.s = s or o.s
  186. return o
  187. end
  188. function StringReader:Peek()
  189. local i = self.i + 1
  190. if i <= #self.s then
  191. return string.sub(self.s, i, i)
  192. end
  193. return nil
  194. end
  195. function StringReader:Next()
  196. self.i = self.i+1
  197. if self.i <= #self.s then
  198. return string.sub(self.s, self.i, self.i)
  199. end
  200. return nil
  201. end
  202. function StringReader:All()
  203. return self.s
  204. end
  205. local JsonReader = {
  206. escapes = {
  207. ['t'] = '\t',
  208. ['n'] = '\n',
  209. ['f'] = '\f',
  210. ['r'] = '\r',
  211. ['b'] = '\b',
  212. }
  213. }
  214. function JsonReader:New(s)
  215. local o = {}
  216. o.reader = StringReader:New(s)
  217. setmetatable(o, self)
  218. self.__index = self
  219. return o;
  220. end
  221. function JsonReader:Read()
  222. self:SkipWhiteSpace()
  223. local peek = self:Peek()
  224. if peek == nil then
  225. error(string.format(
  226. "Nil string: '%s'",
  227. self:All()))
  228. elseif peek == '{' then
  229. return self:ReadObject()
  230. elseif peek == '[' then
  231. return self:ReadArray()
  232. elseif peek == '"' then
  233. return self:ReadString()
  234. elseif string.find(peek, "[%+%-%d]") then
  235. return self:ReadNumber()
  236. elseif peek == 't' then
  237. return self:ReadTrue()
  238. elseif peek == 'f' then
  239. return self:ReadFalse()
  240. elseif peek == 'n' then
  241. return self:ReadNull()
  242. elseif peek == '/' then
  243. self:ReadComment()
  244. return self:Read()
  245. else
  246. error(string.format(
  247. "Invalid input: '%s'",
  248. self:All()))
  249. end
  250. end
  251. function JsonReader:ReadTrue()
  252. self:TestReservedWord{'t','r','u','e'}
  253. return true
  254. end
  255. function JsonReader:ReadFalse()
  256. self:TestReservedWord{'f','a','l','s','e'}
  257. return false
  258. end
  259. function JsonReader:ReadNull()
  260. self:TestReservedWord{'n','u','l','l'}
  261. return nil
  262. end
  263. function JsonReader:TestReservedWord(t)
  264. for i, v in ipairs(t) do
  265. if self:Next() ~= v then
  266. error(string.format(
  267. "Error reading '%s': %s",
  268. table.concat(t),
  269. self:All()))
  270. end
  271. end
  272. end
  273. function JsonReader:ReadNumber()
  274. local result = self:Next()
  275. local peek = self:Peek()
  276. while peek ~= nil and string.find(
  277. peek,
  278. "[%+%-%d%.eE]") do
  279. result = result .. self:Next()
  280. peek = self:Peek()
  281. end
  282. result = tonumber(result)
  283. if result == nil then
  284. error(string.format(
  285. "Invalid number: '%s'",
  286. result))
  287. else
  288. return result
  289. end
  290. end
  291. function JsonReader:ReadString()
  292. local result = ""
  293. assert(self:Next() == '"')
  294. while self:Peek() ~= '"' do
  295. local ch = self:Next()
  296. if ch == '\\' then
  297. ch = self:Next()
  298. if self.escapes[ch] then
  299. ch = self.escapes[ch]
  300. end
  301. end
  302. result = result .. ch
  303. end
  304. assert(self:Next() == '"')
  305. return result
  306. --[[local fromunicode = function(m)
  307. return string.char(tonumber(m, 16))
  308. end
  309. return string.gsub(
  310. result,
  311. "u%x%x(%x%x)",
  312. fromunicode)--]]
  313. end
  314. function JsonReader:ReadComment()
  315. assert(self:Next() == '/')
  316. local second = self:Next()
  317. if second == '/' then
  318. self:ReadSingleLineComment()
  319. elseif second == '*' then
  320. self:ReadBlockComment()
  321. else
  322. error(string.format(
  323. "Invalid comment: %s",
  324. self:All()))
  325. end
  326. end
  327. function JsonReader:ReadBlockComment()
  328. local done = false
  329. while not done do
  330. local ch = self:Next()
  331. if ch == '*' and self:Peek() == '/' then
  332. done = true
  333. end
  334. if not done and
  335. ch == '/' and
  336. self:Peek() == "*" then
  337. error(string.format(
  338. "Invalid comment: %s, '/*' illegal.",
  339. self:All()))
  340. end
  341. end
  342. self:Next()
  343. end
  344. function JsonReader:ReadSingleLineComment()
  345. local ch = self:Next()
  346. while ch ~= '\r' and ch ~= '\n' do
  347. ch = self:Next()
  348. end
  349. end
  350. function JsonReader:ReadArray()
  351. local result = {}
  352. assert(self:Next() == '[')
  353. local done = false
  354. if self:Peek() == ']' then
  355. done = true;
  356. end
  357. while not done do
  358. local item = self:Read()
  359. result[#result+1] = item
  360. self:SkipWhiteSpace()
  361. if self:Peek() == ']' then
  362. done = true
  363. end
  364. if not done then
  365. local ch = self:Next()
  366. if ch ~= ',' then
  367. error(string.format(
  368. "Invalid array: '%s' due to: '%s'",
  369. self:All(), ch))
  370. end
  371. end
  372. end
  373. assert(']' == self:Next())
  374. return result
  375. end
  376. function JsonReader:ReadObject()
  377. local result = {}
  378. assert(self:Next() == '{')
  379. local done = false
  380. if self:Peek() == '}' then
  381. done = true
  382. end
  383. while not done do
  384. local key = self:Read()
  385. if type(key) ~= "string" then
  386. error(string.format(
  387. "Invalid non-string object key: %s",
  388. key))
  389. end
  390. self:SkipWhiteSpace()
  391. local ch = self:Next()
  392. if ch ~= ':' then
  393. error(string.format(
  394. "Invalid object: '%s' due to: '%s'",
  395. self:All(),
  396. ch))
  397. end
  398. self:SkipWhiteSpace()
  399. local val = self:Read()
  400. key = tonumber(key) or key
  401. result[key] = val
  402. self:SkipWhiteSpace()
  403. if self:Peek() == '}' then
  404. done = true
  405. end
  406. if not done then
  407. ch = self:Next()
  408. if ch ~= ',' then
  409. error(string.format(
  410. "Invalid array: '%s' near: '%s'",
  411. self:All(),
  412. ch))
  413. end
  414. end
  415. end
  416. assert(self:Next() == "}")
  417. return result
  418. end
  419. function JsonReader:SkipWhiteSpace()
  420. local p = self:Peek()
  421. while p ~= nil and string.find(p, "[%s/]") do
  422. if p == '/' then
  423. self:ReadComment()
  424. else
  425. self:Next()
  426. end
  427. p = self:Peek()
  428. end
  429. end
  430. function JsonReader:Peek()
  431. return self.reader:Peek()
  432. end
  433. function JsonReader:Next()
  434. return self.reader:Next()
  435. end
  436. function JsonReader:All()
  437. return self.reader:All()
  438. end
  439. function Encode(o)
  440. local writer = JsonWriter:New()
  441. writer:Write(o)
  442. return writer:ToString()
  443. end
  444. function Decode(s)
  445. local reader = JsonReader:New(s)
  446. return reader:Read()
  447. end
  448. function Null()
  449. return Null
  450. end