Files
mobile_comm/luatos/air780epm/module/Air780EPM/demo/json/json_app.lua
T
wangfq 173dd6874f init: Air780EPM 官方 LuatOS 项目代码基线
- 来源: 合宙 LuatOS 官方仓库 air780epm 模块完整代码
- 路径: luatos/air780epm/module/Air780EPM/demo 含官方 demo(含 mqtt/mqtts/socket/uart 等)
- 后续: 基于 demo 开发 UART<->MQTT 数据上报功能
2026-08-31 08:53:49 +08:00

277 lines
14 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
--[[
@module json_app
@summary json 序列化与反序列化功能模块
@version 1.0
@date 2025.11.05
@author 马梦阳
@usage
本功能模块演示的内容为:
1.将 Lua 对象 转为 JSON 字符串:
示例一:Lua string 转为 JSON string
示例二:Lua number 转为 JSON string
示例三:Lua boolean 转为 JSON string
示例四:Lua table 转为 JSON string
示例五:Lua nil 转为 JSON string
序列化失败示例和指定浮点数示例;
2.将 JSON 字符串 转为 Lua 对象:
示例一:JSON string 转为 Lua string
示例二:JSON number 转为 Lua number
示例三:JSON boolean 转为 Lua boolean
示例四:JSON table 转为 Lua table
示例五:JSON nil 转为 Lua nil
反序列化失败示例;
空表(empty table)转换为 JSON 时的说明;
字符串中包含控制字符(如 \r\n)的 JSON 序列化与反序列化说明;
json.null 的语义与比较行为说明:
本文件没有对外接口,直接在 main.lua 中 require "json_app" 就可以加载运行;
]]
-- json库支持将 Lua 对象 转为 JSON 字符串, 或者反过来, JSON 字符串 转 Lua 对象
-- 若转换失败, 会返回nil值, 强烈建议在使用时添加额外的判断,如下列演示代码中所示
local function main_task()
while true do
sys.wait(1000)
-- 序列化成功示例:
-- 示例一:Lua string 转为 JSON string
local data = "test"
local json_str, err_msg = json.encode(data)
if json_str == nil then
-- 序列化失败时, 会返回 nil 值, 并通过 err_msg 参数返回错误信息
log.info("string_string_test1","序列化失败:", err_msg)
-- 执行错误处理逻辑,如使用默认值、重试或中止操作
else
-- 序列化成功时, 会返回 JSON 字符串
log.info("string_string_test1","序列化成功:", json_str)
end
-- 示例二:Lua number 转为 JSON string
local data = 123456789
local json_str, err_msg = json.encode(data)
if json_str == nil then
-- 序列化失败时, 会返回 nil 值, 并通过 err_msg 参数返回错误信息
log.info("number_string_test1","序列化失败:", err_msg)
-- 执行错误处理逻辑,如使用默认值、重试或中止操作
else
-- 序列化成功时, 会返回 JSON 字符串
log.info("number_string_test1","序列化成功:", json_str)
end
-- 示例三:Lua boolean 转为 JSON string
local data = true
local json_str, err_msg = json.encode(data)
if json_str == nil then
-- 序列化失败时, 会返回 nil 值, 并通过 err_msg 参数返回错误信息
log.info("boolean_string_test1","序列化失败:", err_msg)
-- 执行错误处理逻辑,如使用默认值、重试或中止操作
else
-- 序列化成功时, 会返回 JSON 字符串
log.info("boolean_string_test1","序列化成功:", json_str)
end
-- 示例四:Lua table 转为 JSON string
local data = {abc = 123, def = "123", ttt = true}
local json_str, err_msg = json.encode(data)
if json_str == nil then
-- 序列化失败时, 会返回 nil 值, 并通过 err_msg 参数返回错误信息
log.info("table_string_test1","序列化失败:", err_msg)
-- 执行错误处理逻辑,如使用默认值、重试或中止操作
else
-- 序列化成功时, 会返回 JSON 字符串
-- 由于 Lua 表在遍历时键的顺序是不确定的(尤其是字符串键)
-- 而 JSON 对象本身也是无序的
-- 因此序列化后的 JSON 字符串中键的顺序可能与 Lua 源码中的书写顺序不同,属于正常情况
log.info("table_string_test1","序列化成功:", json_str)
end
-- 示例五:Lua nil 转为 JSON string
local data = nil
local json_str, err_msg = json.encode(data)
if json_str == nil then
-- 序列化失败时, 会返回 nil 值, 并通过 err_msg 参数返回错误信息
log.info("nil_string_test1","序列化失败:", err_msg)
-- 执行错误处理逻辑,如使用默认值、重试或中止操作
else
-- 序列化成功时, 会返回 JSON 字符串
-- 注意:此时返回值是一个空字符串 ""
log.info("nil_string_test1","序列化成功:", json_str)
end
-- 序列化失败示例:
-- Lua table 中包含 function
local data = {abc = 123, def = "123", ttt = true, err = function() end}
local json_str, err_msg = json.encode(data)
if json_str == nil then
-- 序列化失败时, 会返回 nil 值, 并通过 err_msg 参数返回错误信息
log.info("table_string_test2","序列化失败:", err_msg)
-- 执行错误处理逻辑,如使用默认值、重试或中止操作
else
-- 序列化成功时, 会返回 JSON 字符串
log.info("table_string_test2","序列化成功:", json_str)
end
-- 指定浮点数示例:
-- 指定保留三位小数,不足时补零,超出时四舍五入;
local data = {abc = 1234.56789}
local json_str, err_msg = json.encode(data, "3f")
if json_str == nil then
-- 序列化失败时, 会返回 nil 值, 并通过 err_msg 参数返回错误信息
log.info("table_string_test3","序列化失败:", err_msg)
-- 执行错误处理逻辑,如使用默认值、重试或中止操作
else
-- 序列化成功时, 会返回 JSON 字符串
log.info("table_string_test3","序列化成功:", json_str)
end
-- 反序列化成功示例:
-- 示例一:JSON string 转为 Lua string
local str = '"test"'
-- local str = "\"test\""
local obj, result, err = json.decode(str)
if result == false then
-- 反序列化失败时, 会返回 nil 值, 并通过 err 参数返回错误信息
log.info("string_string_test1","反序列化失败:", err)
-- 执行错误处理逻辑,如使用默认值、重试或中止操作
else
-- 反序列化成功时, 会返回 Lua string
log.info("string_string_test1","反序列化成功:", obj)
end
-- 示例二:JSON string 转为 Lua number
local str = "123456789"
local obj, result, err = json.decode(str)
if result == false then
-- 反序列化失败时, 会返回 nil 值, 并通过 err 参数返回错误信息
log.info("string_number_test1","反序列化失败:", err)
-- 执行错误处理逻辑,如使用默认值、重试或中止操作
else
-- 反序列化成功时, 会返回 Lua number
log.info("string_number_test1","反序列化成功:", obj)
end
-- 示例三:JSON string 转为 Lua boolean
local str = "true"
local obj, result, err = json.decode(str)
if result == false then
-- 反序列化失败时, 会返回 nil 值, 并通过 err 参数返回错误信息
log.info("string_boolean_test1","反序列化失败:", err)
-- 执行错误处理逻辑,如使用默认值、重试或中止操作
else
-- 反序列化成功时, 会返回 Lua boolean
log.info("string_boolean_test1","反序列化成功:", obj)
end
-- 示例四:JSON string 转为 Lua table
local str = "{\"abc\":1234545}"
local obj, result, err = json.decode(str)
if result == false then
-- 反序列化失败时, 会返回 nil 值, 并通过 err 参数返回错误信息
log.info("string_table_test1.2","反序列化失败:", err)
-- 执行错误处理逻辑,如使用默认值、重试或中止操作
else
-- 反序列化成功时, 会返回 Lua table
-- 注意:此时 obj 是一个 Lua table
-- 若直接打印 obj,会输出 table: 01C9A490 类似的内存地址
log.info("string_table_test1.2","反序列化成功:", obj)
-- 需要添加具体的字段名称,才能正确输出
log.info("string_table_test1.2","反序列化成功:", obj.abc)
end
-- 反序列化失败示例:
-- JSON string 不是合法的 JSON 格式;
local str = "{\"def\":}"
local obj, result, err = json.decode(str)
if result == false then
-- 反序列化失败时, 会返回 nil 值, 并通过 err 参数返回错误信息
log.info("string_table_test2","反序列化失败:", err)
-- 执行错误处理逻辑,如使用默认值、重试或中止操作
else
-- 反序列化成功时, 会返回 Lua table
log.info("string_table_test2","反序列化成功:", obj)
end
-- empty table(空表) 转换为 JSON 时的说明:
-- 原生 Lua 中的 table 是数组(sequence)和哈希表(map)的统一数据结构;
-- 空表 {} 在转换为 JSON 时存在歧义:无法确定应输出为空数组 [] 还是空对象 {};
-- 由于 Lua 中只有包含连续正整数索引(从 1 开始)的表才被视为数组,而空表不满足这一条件;
-- 因此 JSON 库默认将其序列化为 {}(空对象);
local data = {abc = {}}
local json_str, err_msg = json.encode(data)
if json_str == nil then
-- 序列化失败时, 会返回 nil 值, 并通过 err_msg 参数返回错误信息
log.info("table_string_test3","序列化失败:", err_msg)
-- 执行错误处理逻辑,如使用默认值、重试或中止操作
else
-- 序列化成功时, 会返回 JSON 字符串
log.info("table_string_test3","序列化成功:", json_str)
end
-- 字符串中包含控制字符(如 \r\n)的 JSON 序列化与反序列化说明:
-- 在 Lua 中,字符串可以包含任意字符,包括回车(\r)、换行(\n)等控制字符;
-- 当使用 json.encode() 对包含此类字符的字符串进行序列化时;
-- JSON 库会自动将其转义为标准的 JSON 字符串字面量形式(例如 \r 转为 "\r"\n 转为 "\n");
-- 以确保生成的 JSON 符合规范且可安全传输;
-- 反序列化时(json.decode()),这些转义序列会被正确还原为原始的控制字符;
-- 因此解码后的字符串与原始字符串在内容上完全一致(逐字节相等);
-- 需要注意的是:日志输出函数(如 log.info)在打印包含 \r\n 的字符串时;
-- 会实际执行回车换行操作,导致日志在终端上分行显示;
-- 这可能造成“输出格式混乱”或“多出缩进/空格”的视觉错觉(例如 true 前有一个空格长度);
-- 但这只是日志显示效果,并非字符串内容本身发生变化;
-- 实际比较(tmp3.str == tmp)结果为 true,证明序列化与反序列化过程是无损且正确的;
local tmp = "ABC\r\nDEF\r\n"
local tmp2, err_msg = json.encode({str=tmp})
if tmp2 == nil then
-- 序列化失败时, 会返回 nil 值, 并通过 err_msg 参数返回错误信息
log.info("json","序列化失败:", err_msg)
-- 执行错误处理逻辑,如使用默认值、重试或中止操作
else
-- 序列化成功时, 会返回 JSON 字符串
log.info("json","序列化成功:", tmp2)
end
local tmp3, result, err = json.decode(tmp2)
if result == false then
-- 反序列化失败时, 会返回 nil 值, 并通过 err 参数返回错误信息
log.info("json","反序列化失败:", err)
-- 执行错误处理逻辑,如使用默认值、重试或中止操作
else
-- 反序列化成功时, 会返回 Lua table
-- 注意:此时 tmp3 是一个 Lua table
-- 直接打印 tmp3 显示的是内存地址,需要添加对应字段
-- true前存在一个空格长度,这是日志输出格式导致的,与字符串内容本身无实际差异
log.info("json","反序列化成功:", tmp3.str, tmp3.str == tmp)
end
-- json.null 的语义与比较行为说明:
-- 在标准 JSON 中,null 是一个合法的字面量,表示“空值”或“无值”;
-- 然而,Lua 语言本身没有 null 类型,只有 nil 用于表示未定义或空值;
-- 为在 Lua 中准确表示 JSON 的 null,json 库提供了一个特殊占位符:json.null;
-- json.null 通常是一个轻量级的 userdata 或 table,具体实现依赖库版本;
-- 当使用 json.encode() 序列化包含 json.null 的字段时,该字段会被正确转换为 JSON 中的 null;
-- 反之,json.decode() 在解析 JSON 中的 null 时,会将其还原为 json.null,而非 Lua 的 nil
-- 这是因为:若将 JSON 的 null 直接转为 nil,会导致 table 中对应键被删除;
-- 从而丢失原始 JSON 的结构信息;
-- 因此,json.decode('{"abc":null}').abc 的结果是 json.null,而不是 nil
-- 由于 json.null 是一个具体的值(非 nil),它与 nil 比较结果为 false;
-- 只有与 json.null 自身比较时,结果才为 true;
-- 开发者应始终使用 == json.null 来判断某个字段是否为 JSON 的 null;
-- 而不要用 == nil,否则逻辑将出错;
log.info("json.null", json.encode({name=json.null}))
-- 日志输出:{"name":null}
log.info("json.null", json.decode("{\"abc\":null}").abc == json.null)
-- 日志输出:true
log.info("json.null", json.decode("{\"abc\":null}").abc == nil)
-- 日志输出:false
end
end
-- 启动主任务
sys.taskInit(main_task)