json_app.lua 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. --[[
  2. @module json_app
  3. @summary json 序列化与反序列化功能模块
  4. @version 1.0
  5. @date 2025.11.05
  6. @author 马梦阳
  7. @usage
  8. 本功能模块演示的内容为:
  9. 1.将 Lua 对象 转为 JSON 字符串:
  10. 示例一:Lua string 转为 JSON string;
  11. 示例二:Lua number 转为 JSON string;
  12. 示例三:Lua boolean 转为 JSON string;
  13. 示例四:Lua table 转为 JSON string;
  14. 示例五:Lua nil 转为 JSON string;
  15. 序列化失败示例和指定浮点数示例;
  16. 2.将 JSON 字符串 转为 Lua 对象:
  17. 示例一:JSON string 转为 Lua string;
  18. 示例二:JSON number 转为 Lua number;
  19. 示例三:JSON boolean 转为 Lua boolean;
  20. 示例四:JSON table 转为 Lua table;
  21. 示例五:JSON nil 转为 Lua nil;
  22. 反序列化失败示例;
  23. 空表(empty table)转换为 JSON 时的说明;
  24. 字符串中包含控制字符(如 \r\n)的 JSON 序列化与反序列化说明;
  25. json.null 的语义与比较行为说明:
  26. 本文件没有对外接口,直接在 main.lua 中 require "json_app" 就可以加载运行;
  27. ]]
  28. -- json库支持将 Lua 对象 转为 JSON 字符串, 或者反过来, JSON 字符串 转 Lua 对象
  29. -- 若转换失败, 会返回nil值, 强烈建议在使用时添加额外的判断,如下列演示代码中所示
  30. local function main_task()
  31. while true do
  32. sys.wait(1000)
  33. -- 序列化成功示例:
  34. -- 示例一:Lua string 转为 JSON string;
  35. local data = "test"
  36. local json_str, err_msg = json.encode(data)
  37. if json_str == nil then
  38. -- 序列化失败时, 会返回 nil 值, 并通过 err_msg 参数返回错误信息
  39. log.info("string_string_test1","序列化失败:", err_msg)
  40. -- 执行错误处理逻辑,如使用默认值、重试或中止操作
  41. else
  42. -- 序列化成功时, 会返回 JSON 字符串
  43. log.info("string_string_test1","序列化成功:", json_str)
  44. end
  45. -- 示例二:Lua number 转为 JSON string;
  46. local data = 123456789
  47. local json_str, err_msg = json.encode(data)
  48. if json_str == nil then
  49. -- 序列化失败时, 会返回 nil 值, 并通过 err_msg 参数返回错误信息
  50. log.info("number_string_test1","序列化失败:", err_msg)
  51. -- 执行错误处理逻辑,如使用默认值、重试或中止操作
  52. else
  53. -- 序列化成功时, 会返回 JSON 字符串
  54. log.info("number_string_test1","序列化成功:", json_str)
  55. end
  56. -- 示例三:Lua boolean 转为 JSON string;
  57. local data = true
  58. local json_str, err_msg = json.encode(data)
  59. if json_str == nil then
  60. -- 序列化失败时, 会返回 nil 值, 并通过 err_msg 参数返回错误信息
  61. log.info("boolean_string_test1","序列化失败:", err_msg)
  62. -- 执行错误处理逻辑,如使用默认值、重试或中止操作
  63. else
  64. -- 序列化成功时, 会返回 JSON 字符串
  65. log.info("boolean_string_test1","序列化成功:", json_str)
  66. end
  67. -- 示例四:Lua table 转为 JSON string;
  68. local data = {abc = 123, def = "123", ttt = true}
  69. local json_str, err_msg = json.encode(data)
  70. if json_str == nil then
  71. -- 序列化失败时, 会返回 nil 值, 并通过 err_msg 参数返回错误信息
  72. log.info("table_string_test1","序列化失败:", err_msg)
  73. -- 执行错误处理逻辑,如使用默认值、重试或中止操作
  74. else
  75. -- 序列化成功时, 会返回 JSON 字符串
  76. -- 由于 Lua 表在遍历时键的顺序是不确定的(尤其是字符串键)
  77. -- 而 JSON 对象本身也是无序的
  78. -- 因此序列化后的 JSON 字符串中键的顺序可能与 Lua 源码中的书写顺序不同,属于正常情况
  79. log.info("table_string_test1","序列化成功:", json_str)
  80. end
  81. -- 示例五:Lua nil 转为 JSON string;
  82. local data = nil
  83. local json_str, err_msg = json.encode(data)
  84. if json_str == nil then
  85. -- 序列化失败时, 会返回 nil 值, 并通过 err_msg 参数返回错误信息
  86. log.info("nil_string_test1","序列化失败:", err_msg)
  87. -- 执行错误处理逻辑,如使用默认值、重试或中止操作
  88. else
  89. -- 序列化成功时, 会返回 JSON 字符串
  90. -- 注意:此时返回值是一个空字符串 ""
  91. log.info("nil_string_test1","序列化成功:", json_str)
  92. end
  93. -- 序列化失败示例:
  94. -- Lua table 中包含 function;
  95. local data = {abc = 123, def = "123", ttt = true, err = function() end}
  96. local json_str, err_msg = json.encode(data)
  97. if json_str == nil then
  98. -- 序列化失败时, 会返回 nil 值, 并通过 err_msg 参数返回错误信息
  99. log.info("table_string_test2","序列化失败:", err_msg)
  100. -- 执行错误处理逻辑,如使用默认值、重试或中止操作
  101. else
  102. -- 序列化成功时, 会返回 JSON 字符串
  103. log.info("table_string_test2","序列化成功:", json_str)
  104. end
  105. -- 指定浮点数示例:
  106. -- 指定保留三位小数,不足时补零,超出时四舍五入;
  107. local data = {abc = 1234.56789}
  108. local json_str, err_msg = json.encode(data, "3f")
  109. if json_str == nil then
  110. -- 序列化失败时, 会返回 nil 值, 并通过 err_msg 参数返回错误信息
  111. log.info("table_string_test3","序列化失败:", err_msg)
  112. -- 执行错误处理逻辑,如使用默认值、重试或中止操作
  113. else
  114. -- 序列化成功时, 会返回 JSON 字符串
  115. log.info("table_string_test3","序列化成功:", json_str)
  116. end
  117. -- 反序列化成功示例:
  118. -- 示例一:JSON string 转为 Lua string
  119. local str = '"test"'
  120. -- local str = "\"test\""
  121. local obj, result, err = json.decode(str)
  122. if result == false then
  123. -- 反序列化失败时, 会返回 nil 值, 并通过 err 参数返回错误信息
  124. log.info("string_string_test1","反序列化失败:", err)
  125. -- 执行错误处理逻辑,如使用默认值、重试或中止操作
  126. else
  127. -- 反序列化成功时, 会返回 Lua string
  128. log.info("string_string_test1","反序列化成功:", obj)
  129. end
  130. -- 示例二:JSON string 转为 Lua number;
  131. local str = "123456789"
  132. local obj, result, err = json.decode(str)
  133. if result == false then
  134. -- 反序列化失败时, 会返回 nil 值, 并通过 err 参数返回错误信息
  135. log.info("string_number_test1","反序列化失败:", err)
  136. -- 执行错误处理逻辑,如使用默认值、重试或中止操作
  137. else
  138. -- 反序列化成功时, 会返回 Lua number
  139. log.info("string_number_test1","反序列化成功:", obj)
  140. end
  141. -- 示例三:JSON string 转为 Lua boolean;
  142. local str = "true"
  143. local obj, result, err = json.decode(str)
  144. if result == false then
  145. -- 反序列化失败时, 会返回 nil 值, 并通过 err 参数返回错误信息
  146. log.info("string_boolean_test1","反序列化失败:", err)
  147. -- 执行错误处理逻辑,如使用默认值、重试或中止操作
  148. else
  149. -- 反序列化成功时, 会返回 Lua boolean
  150. log.info("string_boolean_test1","反序列化成功:", obj)
  151. end
  152. -- 示例四:JSON string 转为 Lua table;
  153. local str = "{\"abc\":1234545}"
  154. local obj, result, err = json.decode(str)
  155. if result == false then
  156. -- 反序列化失败时, 会返回 nil 值, 并通过 err 参数返回错误信息
  157. log.info("string_table_test1.2","反序列化失败:", err)
  158. -- 执行错误处理逻辑,如使用默认值、重试或中止操作
  159. else
  160. -- 反序列化成功时, 会返回 Lua table
  161. -- 注意:此时 obj 是一个 Lua table
  162. -- 若直接打印 obj,会输出 table: 01C9A490 类似的内存地址
  163. log.info("string_table_test1.2","反序列化成功:", obj)
  164. -- 需要添加具体的字段名称,才能正确输出
  165. log.info("string_table_test1.2","反序列化成功:", obj.abc)
  166. end
  167. -- 反序列化失败示例:
  168. -- JSON string 不是合法的 JSON 格式;
  169. local str = "{\"def\":}"
  170. local obj, result, err = json.decode(str)
  171. if result == false then
  172. -- 反序列化失败时, 会返回 nil 值, 并通过 err 参数返回错误信息
  173. log.info("string_table_test2","反序列化失败:", err)
  174. -- 执行错误处理逻辑,如使用默认值、重试或中止操作
  175. else
  176. -- 反序列化成功时, 会返回 Lua table
  177. log.info("string_table_test2","反序列化成功:", obj)
  178. end
  179. -- empty table(空表) 转换为 JSON 时的说明:
  180. -- 原生 Lua 中的 table 是数组(sequence)和哈希表(map)的统一数据结构;
  181. -- 空表 {} 在转换为 JSON 时存在歧义:无法确定应输出为空数组 [] 还是空对象 {};
  182. -- 由于 Lua 中只有包含连续正整数索引(从 1 开始)的表才被视为数组,而空表不满足这一条件;
  183. -- 因此 JSON 库默认将其序列化为 {}(空对象);
  184. local data = {abc = {}}
  185. local json_str, err_msg = json.encode(data)
  186. if json_str == nil then
  187. -- 序列化失败时, 会返回 nil 值, 并通过 err_msg 参数返回错误信息
  188. log.info("table_string_test3","序列化失败:", err_msg)
  189. -- 执行错误处理逻辑,如使用默认值、重试或中止操作
  190. else
  191. -- 序列化成功时, 会返回 JSON 字符串
  192. log.info("table_string_test3","序列化成功:", json_str)
  193. end
  194. -- 字符串中包含控制字符(如 \r\n)的 JSON 序列化与反序列化说明:
  195. -- 在 Lua 中,字符串可以包含任意字符,包括回车(\r)、换行(\n)等控制字符;
  196. -- 当使用 json.encode() 对包含此类字符的字符串进行序列化时;
  197. -- JSON 库会自动将其转义为标准的 JSON 字符串字面量形式(例如 \r 转为 "\r",\n 转为 "\n");
  198. -- 以确保生成的 JSON 符合规范且可安全传输;
  199. -- 反序列化时(json.decode()),这些转义序列会被正确还原为原始的控制字符;
  200. -- 因此解码后的字符串与原始字符串在内容上完全一致(逐字节相等);
  201. -- 需要注意的是:日志输出函数(如 log.info)在打印包含 \r\n 的字符串时;
  202. -- 会实际执行回车换行操作,导致日志在终端上分行显示;
  203. -- 这可能造成“输出格式混乱”或“多出缩进/空格”的视觉错觉(例如 true 前有一个空格长度);
  204. -- 但这只是日志显示效果,并非字符串内容本身发生变化;
  205. -- 实际比较(tmp3.str == tmp)结果为 true,证明序列化与反序列化过程是无损且正确的;
  206. local tmp = "ABC\r\nDEF\r\n"
  207. local tmp2, err_msg = json.encode({str=tmp})
  208. if tmp2 == nil then
  209. -- 序列化失败时, 会返回 nil 值, 并通过 err_msg 参数返回错误信息
  210. log.info("json","序列化失败:", err_msg)
  211. -- 执行错误处理逻辑,如使用默认值、重试或中止操作
  212. else
  213. -- 序列化成功时, 会返回 JSON 字符串
  214. log.info("json","序列化成功:", tmp2)
  215. end
  216. local tmp3, result, err = json.decode(tmp2)
  217. if result == false then
  218. -- 反序列化失败时, 会返回 nil 值, 并通过 err 参数返回错误信息
  219. log.info("json","反序列化失败:", err)
  220. -- 执行错误处理逻辑,如使用默认值、重试或中止操作
  221. else
  222. -- 反序列化成功时, 会返回 Lua table
  223. -- 注意:此时 tmp3 是一个 Lua table
  224. -- 直接打印 tmp3 显示的是内存地址,需要添加对应字段
  225. -- true前存在一个空格长度,这是日志输出格式导致的,与字符串内容本身无实际差异
  226. log.info("json","反序列化成功:", tmp3.str, tmp3.str == tmp)
  227. end
  228. -- json.null 的语义与比较行为说明:
  229. -- 在标准 JSON 中,null 是一个合法的字面量,表示“空值”或“无值”;
  230. -- 然而,Lua 语言本身没有 null 类型,只有 nil 用于表示未定义或空值;
  231. -- 为在 Lua 中准确表示 JSON 的 null,json 库提供了一个特殊占位符:json.null;
  232. -- json.null 通常是一个轻量级的 userdata 或 table,具体实现依赖库版本;
  233. -- 当使用 json.encode() 序列化包含 json.null 的字段时,该字段会被正确转换为 JSON 中的 null;
  234. -- 反之,json.decode() 在解析 JSON 中的 null 时,会将其还原为 json.null,而非 Lua 的 nil;
  235. -- 这是因为:若将 JSON 的 null 直接转为 nil,会导致 table 中对应键被删除;
  236. -- 从而丢失原始 JSON 的结构信息;
  237. -- 因此,json.decode('{"abc":null}').abc 的结果是 json.null,而不是 nil;
  238. -- 由于 json.null 是一个具体的值(非 nil),它与 nil 比较结果为 false;
  239. -- 只有与 json.null 自身比较时,结果才为 true;
  240. -- 开发者应始终使用 == json.null 来判断某个字段是否为 JSON 的 null;
  241. -- 而不要用 == nil,否则逻辑将出错;
  242. log.info("json.null", json.encode({name=json.null}))
  243. -- 日志输出:{"name":null}
  244. log.info("json.null", json.decode("{\"abc\":null}").abc == json.null)
  245. -- 日志输出:true
  246. log.info("json.null", json.decode("{\"abc\":null}").abc == nil)
  247. -- 日志输出:false
  248. end
  249. end
  250. -- 启动主任务
  251. sys.taskInit(main_task)