Bladeren bron

update:更新主流模组的 json 示例代码为最新版

mengyang 3 maanden geleden
bovenliggende
commit
e008569802

+ 276 - 0
module/Air780EHM_Air780EHV_Air780EGH/demo/json/json_app.lua

@@ -0,0 +1,276 @@
+--[[
+@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)

+ 83 - 73
module/Air780EHM_Air780EHV_Air780EGH/demo/json/main.lua

@@ -1,80 +1,90 @@
--- LuaTools需要PROJECT和VERSION这两个信息
-PROJECT = "jsondemo"
-VERSION = "1.0.0"
+--[[
+@module  main
+@summary LuatOS用户应用脚本文件入口,总体调度应用逻辑
+@version 1.0
+@date    2025.11.05
+@author  马梦阳
+@usage
 
--- 引入必要的库文件(lua编写), 内部库不需要require
-sys = require("sys")
+本demo演示的核心功能为:
+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 的语义与比较行为说明:
 
+更多说明参考本目录下的 readme.md 文件;
+]]
+
+
+--[[
+必须定义PROJECT和VERSION变量,Luatools工具会用到这两个变量,远程升级功能也会用到这两个变量
+PROJECT:项目名,ascii string类型
+        可以随便定义,只要不使用,就行
+VERSION:项目版本号,ascii string类型
+        如果使用合宙iot.openluat.com进行远程升级,必须按照"XXX.YYY.ZZZ"三段格式定义:
+            X、Y、Z各表示1位数字,三个X表示的数字可以相同,也可以不同,同理三个Y和三个Z表示的数字也是可以相同,可以不同
+            因为历史原因,YYY这三位数字必须存在,但是没有任何用处,可以一直写为000
+        如果不使用合宙iot.openluat.com进行远程升级,根据自己项目的需求,自定义格式即可
+]]
+PROJECT = "json"
+VERSION = "001.000.000"
+
+
+-- 在日志中打印项目名和项目版本号
 log.info("main", PROJECT, VERSION)
 
--- json库支持将 table 转为 字符串, 或者反过来, 字符串 转 table
--- 若转换失败, 会返回nil值, 强烈建议在使用时添加额外的判断
-sys.taskInit(function()
-    while 1 do
-        sys.wait(1000)
-        -- table 转为 字符串
-        local t = {abc=123, def="123", ttt=true}
-        local jdata = json.encode(t)
-        log.info("json", jdata)  									--日志输出:{"ttt":true,"def":"123","abc":123}
-
-        -- 字符串转table
-        local str = "{\"abc\":1234545}" -- 字符串可以来源于任何地方,网络,文本,用户输入,都可以
-        local t = json.decode(str)
-        if t then
-			-- 若解码成功,t不为nil
-			log.info("json", "decode", t.abc) 						--日志输出:decode	1234545
-		else
-			-- 若解码失败,t为nil
-			log.info("json", "decode failed")
-		end
-
-        -- lua中的table是 数组和hashmap的混合体
-        -- 这对json来说会有一些困扰, 尤其是空的table
-        local t = {abc={}}
-        -- 假设从业务上需要输出 {"abc":[]}
-        -- 实际会输出 {"abc": {}} , 空table是优先输出 hashmap (即字典模式)形式, 而非数组形式,Lua语言中数组优先级低于hashmap优先级
-        log.info("json", "encode", json.encode(t)) 					--日志输出:encode	{"abc":{}}
-        -- 混合场景, json场景应避免使用
-        t.abc.def = "123"
-        t.abc[1] = 345
-        -- 输出的内容是 {"abc":{"1":345,"def":"123"}}
-        log.info("json", "encode2", json.encode(t))  				--日志输出:encode2	{"abc":{"1":345,"def":"123"}}
-
-        -- 浮点数演示
-        log.info("json", json.encode({abc=1234.300}))  				--日志输出:{"abc":1234.300}
-        -- 限制小数点到1位
-        log.info("json", json.encode({abc=1234.300}, "1f")) 		--日志输出:{"abc":1234.3}
-
- 
-        local tmp = "ABC\r\nDEF\r\n"
-        local tmp2 = json.encode({str=tmp}) --在JSON中,\r\n 被保留为字符串的一部分
-        log.info("json", tmp2)                                    	--日志输出:{"str":"ABC\r\nDEF\r\n"}
-        local tmp3 = json.decode(tmp2)								
-        log.info("json", "tmp3", tmp3.str, tmp3.str == tmp)			--日志输出:tmp3	ABC
-																		--DEF
-																		--		true  注:true前存在一个TAB长度(这个TAB原因未知,但不影响使用)
-        -- break
-
-        log.info("json.null", json.encode({name=json.null}))		--日志输出:{}  为空对象
-        log.info("json.null", json.decode("{\"abc\":null}").abc == json.null)  	--日志输出:false    在 Lua 中,nil 是一种特殊类型,用于表示“无值”或“未定义”。它与任何其他值(包括自定义的 json.null)都不相等
-        log.info("json.null", json.decode("{\"abc\":null}").abc == nil)			 --日志输出:false
-
-    end
-end)
-
-
--- 这里演示4G模块上网后,会自动点亮网络灯,方便用户判断模块是否正常开机
-sys.taskInit(function()
-    while true do
-        sys.wait(6000)
-                if mobile.status() == 1 then
-                        gpio.set(27, 1)  
-                else
-                        gpio.set(27, 0) 
-                        mobile.reset()
-        end
-    end
-end)
+
+-- 如果内核固件支持wdt看门狗功能,此处对看门狗进行初始化和定时喂狗处理
+-- 如果脚本程序死循环卡死,就会无法及时喂狗,最终会自动重启
+if wdt then
+    --配置喂狗超时时间为9秒钟
+    wdt.init(9000)
+    --启动一个循环定时器,每隔3秒钟喂一次狗
+    sys.timerLoopStart(wdt.feed, 3000)
+end
+
+
+-- 如果内核固件支持errDump功能,此处进行配置,【强烈建议打开此处的注释】
+-- 因为此功能模块可以记录并且上传脚本在运行过程中出现的语法错误或者其他自定义的错误信息,可以初步分析一些设备运行异常的问题
+-- 以下代码是最基本的用法,更复杂的用法可以详细阅读API说明文档
+-- 启动errDump日志存储并且上传功能,600秒上传一次
+-- if errDump then
+--     errDump.config(true, 600)
+-- end
+
+
+-- 使用LuatOS开发的任何一个项目,都强烈建议使用远程升级FOTA功能
+-- 可以使用合宙的iot.openluat.com平台进行远程升级
+-- 也可以使用客户自己搭建的平台进行远程升级
+-- 远程升级的详细用法,可以参考fota的demo进行使用
+
+
+-- 启动一个循环定时器
+-- 每隔3秒钟打印一次总内存,实时的已使用内存,历史最高的已使用内存情况
+-- 方便分析内存使用是否有异常
+-- sys.timerLoopStart(function()
+--     log.info("mem.lua", rtos.meminfo())
+--     log.info("mem.sys", rtos.meminfo("sys"))
+-- end, 3000)
+
+
+-- 加载 json 应用模块
+require "json_app"
+
+
 -- 用户代码已结束---------------------------------------------
 -- 结尾总是这一句
 sys.run()

+ 88 - 0
module/Air780EHM_Air780EHV_Air780EGH/demo/json/readme.md

@@ -0,0 +1,88 @@
+## 演示模块概述
+
+1、main.lua:主程序入口;
+
+2、json_app.lua:json 序列化与反序列化功能模块;
+
+## 演示功能概述
+
+使用 Air780EHM/EHV/EGH 核心板搭配 json 库演示 json 序列化与反序列化功能;
+
+演示分为两部分:
+
+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 的语义与比较行为说明:
+
+## 演示硬件环境
+
+1、Air780EHM/EHV/EGH 核心板一块
+
+2、TYPE-C USB数据线一根
+
+## 演示软件环境
+
+1、[Luatools下载调试工具](https://docs.openluat.com/air8000/luatos/common/download/)
+
+2、[Air780EHM V2016 版本](https://docs.openluat.com/air780epm/luatos/firmware/version/)(理论上最新版本固件也可以,如果使用最新版本的固件不可以,可以烧录 V2016-1 固件对比验证)
+
+3、[Air780EHV V2016 版本](https://docs.openluat.com/air780ehv/luatos/firmware/version/)(理论上最新版本固件也可以,如果使用最新版本的固件不可以,可以烧录 V2016-1 固件对比验证)
+
+4、[Air780EGH V2016 版本](https://docs.openluat.com/air780egh/luatos/firmware/version/)(理论上最新版本固件也可以,如果使用最新版本的固件不可以,可以烧录 V2016-1 固件对比验证)
+
+## 演示核心步骤
+
+1、搭建好硬件环境
+
+2、Luatools 工具烧录内核固件和 demo 脚本代码
+
+3、烧录成功后,自动开机运行
+
+4、正常运行情况时的日志如下:
+
+```
+[00000001.009] I/user.string_string_test1 序列化成功: "test"
+[00000001.009] I/user.number_string_test1 序列化成功: 123456789
+[00000001.010] I/user.boolean_string_test1 序列化成功: true
+[00000001.010] I/user.table_string_test1 序列化成功: {"abc":123,"ttt":true,"def":"123"}
+[00000001.010] I/user.nil_string_test1 序列化成功:
+[00000001.011] I/user.table_string_test2 序列化失败: Cannot serialise function: type not supported
+[00000001.011] I/user.table_string_test3 序列化成功: {"abc":1234.568}
+[00000001.011] I/user.string_string_test1 反序列化成功: test
+[00000001.011] I/user.string_number_test1 反序列化成功: 123456789
+[00000001.011] I/user.string_boolean_test1 反序列化成功: true
+[00000001.011] I/user.string_table_test1.2 反序列化成功: table: 01FE5010
+[00000001.011] I/user.string_table_test1.2 反序列化成功: 1234545
+[00000001.011] I/user.string_table_test2 反序列化失败: Expected value but found T_OBJ_END at character 8
+[00000001.012] I/user.table_string_test3 序列化成功: {"abc":{}}
+[00000001.012] I/user.json 序列化成功: {"str":"ABC\r\nDEF\r\n"}
+[00000001.012] I/user.json 反序列化成功: ABC
+DEF
+ true
+[00000001.012] I/user.json.null {"name":null}
+[00000001.012] I/user.json.null true
+[00000001.012] I/user.json.null false
+```
+

+ 276 - 0
module/Air780EPM/demo/json/json_app.lua

@@ -0,0 +1,276 @@
+--[[
+@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)

+ 83 - 73
module/Air780EPM/demo/json/main.lua

@@ -1,80 +1,90 @@
--- LuaTools需要PROJECT和VERSION这两个信息
-PROJECT = "jsondemo"
-VERSION = "1.0.0"
+--[[
+@module  main
+@summary LuatOS用户应用脚本文件入口,总体调度应用逻辑
+@version 1.0
+@date    2025.11.05
+@author  马梦阳
+@usage
 
--- 引入必要的库文件(lua编写), 内部库不需要require
-sys = require("sys")
+本demo演示的核心功能为:
+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 的语义与比较行为说明:
 
+更多说明参考本目录下的 readme.md 文件;
+]]
+
+
+--[[
+必须定义PROJECT和VERSION变量,Luatools工具会用到这两个变量,远程升级功能也会用到这两个变量
+PROJECT:项目名,ascii string类型
+        可以随便定义,只要不使用,就行
+VERSION:项目版本号,ascii string类型
+        如果使用合宙iot.openluat.com进行远程升级,必须按照"XXX.YYY.ZZZ"三段格式定义:
+            X、Y、Z各表示1位数字,三个X表示的数字可以相同,也可以不同,同理三个Y和三个Z表示的数字也是可以相同,可以不同
+            因为历史原因,YYY这三位数字必须存在,但是没有任何用处,可以一直写为000
+        如果不使用合宙iot.openluat.com进行远程升级,根据自己项目的需求,自定义格式即可
+]]
+PROJECT = "json"
+VERSION = "001.000.000"
+
+
+-- 在日志中打印项目名和项目版本号
 log.info("main", PROJECT, VERSION)
 
--- json库支持将 table 转为 字符串, 或者反过来, 字符串 转 table
--- 若转换失败, 会返回nil值, 强烈建议在使用时添加额外的判断
-sys.taskInit(function()
-    while 1 do
-        sys.wait(1000)
-        -- table 转为 字符串
-        local t = {abc=123, def="123", ttt=true}
-        local jdata = json.encode(t)
-        log.info("json", jdata)  									--日志输出:{"ttt":true,"def":"123","abc":123}
-
-        -- 字符串转table
-        local str = "{\"abc\":1234545}" -- 字符串可以来源于任何地方,网络,文本,用户输入,都可以
-        local t = json.decode(str)
-        if t then
-			-- 若解码成功,t不为nil
-			log.info("json", "decode", t.abc) 						--日志输出:decode	1234545
-		else
-			-- 若解码失败,t为nil
-			log.info("json", "decode failed")
-		end
-
-        -- lua中的table是 数组和hashmap的混合体
-        -- 这对json来说会有一些困扰, 尤其是空的table
-        local t = {abc={}}
-        -- 假设从业务上需要输出 {"abc":[]}
-        -- 实际会输出 {"abc": {}} , 空table是优先输出 hashmap (即字典模式)形式, 而非数组形式,Lua语言中数组优先级低于hashmap优先级
-        log.info("json", "encode", json.encode(t)) 					--日志输出:encode	{"abc":{}}
-        -- 混合场景, json场景应避免使用
-        t.abc.def = "123"
-        t.abc[1] = 345
-        -- 输出的内容是 {"abc":{"1":345,"def":"123"}}
-        log.info("json", "encode2", json.encode(t))  				--日志输出:encode2	{"abc":{"1":345,"def":"123"}}
-
-        -- 浮点数演示
-        log.info("json", json.encode({abc=1234.300}))  				--日志输出:{"abc":1234.300}
-        -- 限制小数点到1位
-        log.info("json", json.encode({abc=1234.300}, "1f")) 		--日志输出:{"abc":1234.3}
-
- 
-        local tmp = "ABC\r\nDEF\r\n"
-        local tmp2 = json.encode({str=tmp}) --在JSON中,\r\n 被保留为字符串的一部分
-        log.info("json", tmp2)                                    	--日志输出:{"str":"ABC\r\nDEF\r\n"}
-        local tmp3 = json.decode(tmp2)								
-        log.info("json", "tmp3", tmp3.str, tmp3.str == tmp)			--日志输出:tmp3	ABC
-																		--DEF
-																		--		true  注:true前存在一个TAB长度(这个TAB原因未知,但不影响使用)
-        -- break
-
-        log.info("json.null", json.encode({name=json.null}))		--日志输出:{}  为空对象
-        log.info("json.null", json.decode("{\"abc\":null}").abc == json.null)  	--日志输出:false    在 Lua 中,nil 是一种特殊类型,用于表示“无值”或“未定义”。它与任何其他值(包括自定义的 json.null)都不相等
-        log.info("json.null", json.decode("{\"abc\":null}").abc == nil)			 --日志输出:false
-
-    end
-end)
-
-
--- 这里演示4G模块上网后,会自动点亮网络灯,方便用户判断模块是否正常开机
-sys.taskInit(function()
-    while true do
-        sys.wait(6000)
-                if mobile.status() == 1 then
-                        gpio.set(27, 1)  
-                else
-                        gpio.set(27, 0) 
-                        mobile.reset()
-        end
-    end
-end)
+
+-- 如果内核固件支持wdt看门狗功能,此处对看门狗进行初始化和定时喂狗处理
+-- 如果脚本程序死循环卡死,就会无法及时喂狗,最终会自动重启
+if wdt then
+    --配置喂狗超时时间为9秒钟
+    wdt.init(9000)
+    --启动一个循环定时器,每隔3秒钟喂一次狗
+    sys.timerLoopStart(wdt.feed, 3000)
+end
+
+
+-- 如果内核固件支持errDump功能,此处进行配置,【强烈建议打开此处的注释】
+-- 因为此功能模块可以记录并且上传脚本在运行过程中出现的语法错误或者其他自定义的错误信息,可以初步分析一些设备运行异常的问题
+-- 以下代码是最基本的用法,更复杂的用法可以详细阅读API说明文档
+-- 启动errDump日志存储并且上传功能,600秒上传一次
+-- if errDump then
+--     errDump.config(true, 600)
+-- end
+
+
+-- 使用LuatOS开发的任何一个项目,都强烈建议使用远程升级FOTA功能
+-- 可以使用合宙的iot.openluat.com平台进行远程升级
+-- 也可以使用客户自己搭建的平台进行远程升级
+-- 远程升级的详细用法,可以参考fota的demo进行使用
+
+
+-- 启动一个循环定时器
+-- 每隔3秒钟打印一次总内存,实时的已使用内存,历史最高的已使用内存情况
+-- 方便分析内存使用是否有异常
+-- sys.timerLoopStart(function()
+--     log.info("mem.lua", rtos.meminfo())
+--     log.info("mem.sys", rtos.meminfo("sys"))
+-- end, 3000)
+
+
+-- 加载 json 应用模块
+require "json_app"
+
+
 -- 用户代码已结束---------------------------------------------
 -- 结尾总是这一句
 sys.run()

+ 84 - 0
module/Air780EPM/demo/json/readme.md

@@ -0,0 +1,84 @@
+## 演示模块概述
+
+1、main.lua:主程序入口;
+
+2、json_app.lua:json 序列化与反序列化功能模块;
+
+## 演示功能概述
+
+使用 Air780EPM 核心板搭配 json 库演示 json 序列化与反序列化功能;
+
+演示分为两部分:
+
+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 的语义与比较行为说明:
+
+## 演示硬件环境
+
+1、Air780EPM 核心板一块
+
+2、TYPE-C USB数据线一根
+
+## 演示软件环境
+
+1、[Luatools下载调试工具](https://docs.openluat.com/air8000/luatos/common/download/)
+
+2、[Air780EPM V2016 版本](https://docs.openluat.com/air780epm/luatos/firmware/version/)(理论上最新版本固件也可以,如果使用最新版本的固件不可以,可以烧录 V2016-1 固件对比验证)
+
+## 演示核心步骤
+
+1、搭建好硬件环境
+
+2、Luatools 工具烧录内核固件和 demo 脚本代码
+
+3、烧录成功后,自动开机运行
+
+4、正常运行情况时的日志如下:
+
+```
+[00000001.009] I/user.string_string_test1 序列化成功: "test"
+[00000001.009] I/user.number_string_test1 序列化成功: 123456789
+[00000001.010] I/user.boolean_string_test1 序列化成功: true
+[00000001.010] I/user.table_string_test1 序列化成功: {"abc":123,"ttt":true,"def":"123"}
+[00000001.010] I/user.nil_string_test1 序列化成功:
+[00000001.011] I/user.table_string_test2 序列化失败: Cannot serialise function: type not supported
+[00000001.011] I/user.table_string_test3 序列化成功: {"abc":1234.568}
+[00000001.011] I/user.string_string_test1 反序列化成功: test
+[00000001.011] I/user.string_number_test1 反序列化成功: 123456789
+[00000001.011] I/user.string_boolean_test1 反序列化成功: true
+[00000001.011] I/user.string_table_test1.2 反序列化成功: table: 01FE5010
+[00000001.011] I/user.string_table_test1.2 反序列化成功: 1234545
+[00000001.011] I/user.string_table_test2 反序列化失败: Expected value but found T_OBJ_END at character 8
+[00000001.012] I/user.table_string_test3 序列化成功: {"abc":{}}
+[00000001.012] I/user.json 序列化成功: {"str":"ABC\r\nDEF\r\n"}
+[00000001.012] I/user.json 反序列化成功: ABC
+DEF
+ true
+[00000001.012] I/user.json.null {"name":null}
+[00000001.012] I/user.json.null true
+[00000001.012] I/user.json.null false
+```
+

+ 276 - 0
module/Air8000/demo/json/json_app.lua

@@ -0,0 +1,276 @@
+--[[
+@module  json_app
+@summary json 序列化与反序列化功能模块
+@version 1.0
+@date    2025.10.29
+@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)

+ 83 - 73
module/Air8000/demo/json/main.lua

@@ -1,80 +1,90 @@
--- LuaTools需要PROJECT和VERSION这两个信息
-PROJECT = "jsondemo"
-VERSION = "1.0.0"
+--[[
+@module  main
+@summary LuatOS用户应用脚本文件入口,总体调度应用逻辑
+@version 1.0
+@date    2025.10.29
+@author  马梦阳
+@usage
 
--- 引入必要的库文件(lua编写), 内部库不需要require
-sys = require("sys")
+本demo演示的核心功能为:
+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 的语义与比较行为说明:
 
+更多说明参考本目录下的 readme.md 文件;
+]]
+
+
+--[[
+必须定义PROJECT和VERSION变量,Luatools工具会用到这两个变量,远程升级功能也会用到这两个变量
+PROJECT:项目名,ascii string类型
+        可以随便定义,只要不使用,就行
+VERSION:项目版本号,ascii string类型
+        如果使用合宙iot.openluat.com进行远程升级,必须按照"XXX.YYY.ZZZ"三段格式定义:
+            X、Y、Z各表示1位数字,三个X表示的数字可以相同,也可以不同,同理三个Y和三个Z表示的数字也是可以相同,可以不同
+            因为历史原因,YYY这三位数字必须存在,但是没有任何用处,可以一直写为000
+        如果不使用合宙iot.openluat.com进行远程升级,根据自己项目的需求,自定义格式即可
+]]
+PROJECT = "json"
+VERSION = "001.000.000"
+
+
+-- 在日志中打印项目名和项目版本号
 log.info("main", PROJECT, VERSION)
 
--- json库支持将 table 转为 字符串, 或者反过来, 字符串 转 table
--- 若转换失败, 会返回nil值, 强烈建议在使用时添加额外的判断
-sys.taskInit(function()
-    while 1 do
-        sys.wait(1000)
-        -- table 转为 字符串
-        local t = {abc=123, def="123", ttt=true}
-        local jdata = json.encode(t)
-        log.info("json", jdata)  									--日志输出:{"ttt":true,"def":"123","abc":123}
-
-        -- 字符串转table
-        local str = "{\"abc\":1234545}" -- 字符串可以来源于任何地方,网络,文本,用户输入,都可以
-        local t = json.decode(str)
-        if t then
-			-- 若解码成功,t不为nil
-			log.info("json", "decode", t.abc) 						--日志输出:decode	1234545
-		else
-			-- 若解码失败,t为nil
-			log.info("json", "decode failed")
-		end
-
-        -- lua中的table是 数组和hashmap的混合体
-        -- 这对json来说会有一些困扰, 尤其是空的table
-        local t = {abc={}}
-        -- 假设从业务上需要输出 {"abc":[]}
-        -- 实际会输出 {"abc": {}} , 空table是优先输出 hashmap (即字典模式)形式, 而非数组形式,Lua语言中数组优先级低于hashmap优先级
-        log.info("json", "encode", json.encode(t)) 					--日志输出:encode	{"abc":{}}
-        -- 混合场景, json场景应避免使用
-        t.abc.def = "123"
-        t.abc[1] = 345
-        -- 输出的内容是 {"abc":{"1":345,"def":"123"}}
-        log.info("json", "encode2", json.encode(t))  				--日志输出:encode2	{"abc":{"1":345,"def":"123"}}
-
-        -- 浮点数演示
-        log.info("json", json.encode({abc=1234.300}))  				--日志输出:{"abc":1234.300}
-        -- 限制小数点到1位
-        log.info("json", json.encode({abc=1234.300}, "1f")) 		--日志输出:{"abc":1234.3}
-
- 
-        local tmp = "ABC\r\nDEF\r\n"
-        local tmp2 = json.encode({str=tmp}) --在JSON中,\r\n 被保留为字符串的一部分
-        log.info("json", tmp2)                                    	--日志输出:{"str":"ABC\r\nDEF\r\n"}
-        local tmp3 = json.decode(tmp2)								
-        log.info("json", "tmp3", tmp3.str, tmp3.str == tmp)			--日志输出:tmp3	ABC
-																		--DEF
-																		--		true  注:true前存在一个TAB长度(这个TAB原因未知,但不影响使用)
-        -- break
-
-        log.info("json.null", json.encode({name=json.null}))		--日志输出:{}  为空对象
-        log.info("json.null", json.decode("{\"abc\":null}").abc == json.null)  	--日志输出:false    在 Lua 中,nil 是一种特殊类型,用于表示“无值”或“未定义”。它与任何其他值(包括自定义的 json.null)都不相等
-        log.info("json.null", json.decode("{\"abc\":null}").abc == nil)			 --日志输出:false
-
-    end
-end)
-
-
--- 这里演示4G模块上网后,会自动点亮网络灯,方便用户判断模块是否正常开机
-sys.taskInit(function()
-    while true do
-        sys.wait(6000)
-                if mobile.status() == 1 then
-                        gpio.set(27, 1)  
-                else
-                        gpio.set(27, 0) 
-                        mobile.reset()
-        end
-    end
-end)
+
+-- 如果内核固件支持wdt看门狗功能,此处对看门狗进行初始化和定时喂狗处理
+-- 如果脚本程序死循环卡死,就会无法及时喂狗,最终会自动重启
+if wdt then
+    --配置喂狗超时时间为9秒钟
+    wdt.init(9000)
+    --启动一个循环定时器,每隔3秒钟喂一次狗
+    sys.timerLoopStart(wdt.feed, 3000)
+end
+
+
+-- 如果内核固件支持errDump功能,此处进行配置,【强烈建议打开此处的注释】
+-- 因为此功能模块可以记录并且上传脚本在运行过程中出现的语法错误或者其他自定义的错误信息,可以初步分析一些设备运行异常的问题
+-- 以下代码是最基本的用法,更复杂的用法可以详细阅读API说明文档
+-- 启动errDump日志存储并且上传功能,600秒上传一次
+-- if errDump then
+--     errDump.config(true, 600)
+-- end
+
+
+-- 使用LuatOS开发的任何一个项目,都强烈建议使用远程升级FOTA功能
+-- 可以使用合宙的iot.openluat.com平台进行远程升级
+-- 也可以使用客户自己搭建的平台进行远程升级
+-- 远程升级的详细用法,可以参考fota的demo进行使用
+
+
+-- 启动一个循环定时器
+-- 每隔3秒钟打印一次总内存,实时的已使用内存,历史最高的已使用内存情况
+-- 方便分析内存使用是否有异常
+-- sys.timerLoopStart(function()
+--     log.info("mem.lua", rtos.meminfo())
+--     log.info("mem.sys", rtos.meminfo("sys"))
+-- end, 3000)
+
+
+-- 加载 json 应用模块
+require "json_app"
+
+
 -- 用户代码已结束---------------------------------------------
 -- 结尾总是这一句
 sys.run()

+ 84 - 0
module/Air8000/demo/json/readme.md

@@ -0,0 +1,84 @@
+## 演示模块概述
+
+1、main.lua:主程序入口;
+
+2、json_app.lua:json 序列化与反序列化功能模块;
+
+## 演示功能概述
+
+使用 Air8000 核心板搭配 json 库演示 json 序列化与反序列化功能;
+
+演示分为两部分:
+
+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 的语义与比较行为说明:
+
+## 演示硬件环境
+
+1、Air8000 核心板一块
+
+2、TYPE-C USB数据线一根
+
+## 演示软件环境
+
+1、[Luatools下载调试工具](https://docs.openluat.com/air8000/luatos/common/download/)
+
+2、[Air8000 V2016 版本](https://docs.openluat.com/air8000/luatos/common/download/)(理论上最新版本固件也可以,如果使用最新版本的固件不可以,可以烧录 V2016-1 固件对比验证)
+
+## 演示核心步骤
+
+1、搭建好硬件环境
+
+2、Luatools 工具烧录内核固件和 demo 脚本代码
+
+3、烧录成功后,自动开机运行
+
+4、正常运行情况时的日志如下:
+
+```
+[00000001.009] I/user.string_string_test1 序列化成功: "test"
+[00000001.009] I/user.number_string_test1 序列化成功: 123456789
+[00000001.010] I/user.boolean_string_test1 序列化成功: true
+[00000001.010] I/user.table_string_test1 序列化成功: {"abc":123,"ttt":true,"def":"123"}
+[00000001.010] I/user.nil_string_test1 序列化成功:
+[00000001.011] I/user.table_string_test2 序列化失败: Cannot serialise function: type not supported
+[00000001.011] I/user.table_string_test3 序列化成功: {"abc":1234.568}
+[00000001.011] I/user.string_string_test1 反序列化成功: test
+[00000001.011] I/user.string_number_test1 反序列化成功: 123456789
+[00000001.011] I/user.string_boolean_test1 反序列化成功: true
+[00000001.011] I/user.string_table_test1.2 反序列化成功: table: 01FE5010
+[00000001.011] I/user.string_table_test1.2 反序列化成功: 1234545
+[00000001.011] I/user.string_table_test2 反序列化失败: Expected value but found T_OBJ_END at character 8
+[00000001.012] I/user.table_string_test3 序列化成功: {"abc":{}}
+[00000001.012] I/user.json 序列化成功: {"str":"ABC\r\nDEF\r\n"}
+[00000001.012] I/user.json 反序列化成功: ABC
+DEF
+ true
+[00000001.012] I/user.json.null {"name":null}
+[00000001.012] I/user.json.null true
+[00000001.012] I/user.json.null false
+```
+

+ 276 - 0
module/Air8101/demo/json/json_app.lua

@@ -0,0 +1,276 @@
+--[[
+@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)

+ 80 - 58
module/Air8101/demo/json/main.lua

@@ -1,69 +1,91 @@
--- main.lua文件
--- LuaTools需要PROJECT和VERSION这两个信息
-PROJECT = "json_demo"
-VERSION = "1.0.0"
+--[[
+@module  main
+@summary LuatOS用户应用脚本文件入口,总体调度应用逻辑
+@version 1.0
+@date    2025.11.05
+@author  马梦阳
+@usage
 
+本demo演示的核心功能为:
+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 的语义与比较行为说明:
+
+更多说明参考本目录下的 readme.md 文件;
+]]
+
+
+--[[
+必须定义PROJECT和VERSION变量,Luatools工具会用到这两个变量,远程升级功能也会用到这两个变量
+PROJECT:项目名,ascii string类型
+        可以随便定义,只要不使用,就行
+VERSION:项目版本号,ascii string类型
+        如果使用合宙iot.openluat.com进行远程升级,必须按照"XXX.YYY.ZZZ"三段格式定义:
+            X、Y、Z各表示1位数字,三个X表示的数字可以相同,也可以不同,同理三个Y和三个Z表示的数字也是可以相同,可以不同
+            因为历史原因,YYY这三位数字必须存在,但是没有任何用处,可以一直写为000
+        如果不使用合宙iot.openluat.com进行远程升级,根据自己项目的需求,自定义格式即可
+]]
+PROJECT = "json"
+VERSION = "001.000.000"
+
+
+-- 在日志中打印项目名和项目版本号
 log.info("main", PROJECT, VERSION)
 
--- json库支持将 table 转为 字符串, 或者反过来, 字符串 转 table
--- 若转换失败, 会返回nil值, 强烈建议在使用时添加额外的判断
-sys.taskInit(function()
-
-        sys.wait(1000)
-        -- table 转为 字符串
-        local t = {abc=123, def="123", ttt=true}
-        local jdata = json.encode(t)
-        log.info("json", jdata)                     --日志输出:{"ttt":true,"def":"123","abc":123}
-
-        -- 字符串转table
-        local str = "{\"abc\":1234545}" -- 字符串可以来源于任何地方,网络,文本,用户输入,都可以
-        local t = json.decode(str)
-        if t then
-                        -- 若解码成功,t不为nil
-                        log.info("json", "decode", t.abc) --日志输出:decode        1234545
-                else
-                        -- 若解码失败,t为nil
-                        log.info("json", "decode failed")
-                end
-
-        -- lua中的table是 数组和hashmap的混合体
-        -- 这对json来说会有一些困扰, 尤其是空的table
-        local t = {abc={}}
-        -- 假设从业务上需要输出 {"abc":[]}
-        -- 实际会输出 {"abc": {}} , 空table是优先输出 hashmap (即字典模式)形式, 而非数组形式,Lua语言中数组优先级低于hashmap优先级
-        log.info("json", "encode", json.encode(t))  --日志输出:encode        {"abc":{}}
-        -- 混合场景, json场景应避免使用
-        t.abc.def = "123"
-        t.abc[1] = 345
-        -- 输出的内容是 {"abc":{"1":345,"def":"123"}}
-        log.info("json", "encode2", json.encode(t)) --日志输出:encode2        {"abc":{"1":345,"def":"123"}}
-
-        -- 浮点数演示
-        log.info("json", json.encode({abc=1234.300}))--日志输出:{"abc":1234.300}
-        -- 限制小数点到1位
-        log.info("json", json.encode({abc=1234.300}, "1f")) --日志输出:{"abc":1234.3}
-
-
-        local tmp = "ABC\r\nDEF\r\n"
-        local tmp2 = json.encode({str=tmp}) --在JSON中,\r\n 被保留为字符串的一部分
-        log.info("json", tmp2)              --日志输出:{"str":"ABC\r\nDEF\r\n"}
-        local tmp3 = json.decode(tmp2)
-        log.info("json", "tmp3", tmp3.str, tmp3.str == tmp) --日志输出:tmp3        ABC
-                                                            --DEF
-                                                            --                true  注:true前存在一个TAB长度(这个TAB原因未知,但不影响使用)
-        -- break
-
-        log.info("json.null", json.encode({name=json.null}))                --日志输出:{}  为空对象
-        log.info("json.null", json.decode("{\"abc\":null}").abc == json.null) --日志输出:false    在 Lua 中,nil 是一种特殊类型,用于表示“无值”或“未定义”。它与任何其他值(包括自定义的 json.null)都不相等
-        log.info("json.null", json.decode("{\"abc\":null}").abc == nil)       --日志输出:false
-
-end)
 
+-- 如果内核固件支持wdt看门狗功能,此处对看门狗进行初始化和定时喂狗处理
+-- 如果脚本程序死循环卡死,就会无法及时喂狗,最终会自动重启
+if wdt then
+    --配置喂狗超时时间为9秒钟
+    wdt.init(9000)
+    --启动一个循环定时器,每隔3秒钟喂一次狗
+    sys.timerLoopStart(wdt.feed, 3000)
+end
+
+
+-- 如果内核固件支持errDump功能,此处进行配置,【强烈建议打开此处的注释】
+-- 因为此功能模块可以记录并且上传脚本在运行过程中出现的语法错误或者其他自定义的错误信息,可以初步分析一些设备运行异常的问题
+-- 以下代码是最基本的用法,更复杂的用法可以详细阅读API说明文档
+-- 启动errDump日志存储并且上传功能,600秒上传一次
+-- if errDump then
+--     errDump.config(true, 600)
+-- end
 
 
+-- 使用LuatOS开发的任何一个项目,都强烈建议使用远程升级FOTA功能
+-- 可以使用合宙的iot.openluat.com平台进行远程升级
+-- 也可以使用客户自己搭建的平台进行远程升级
+-- 远程升级的详细用法,可以参考fota的demo进行使用
+
+
+-- 启动一个循环定时器
+-- 每隔3秒钟打印一次总内存,实时的已使用内存,历史最高的已使用内存情况
+-- 方便分析内存使用是否有异常
+-- sys.timerLoopStart(function()
+--     log.info("mem.lua", rtos.meminfo())
+--     log.info("mem.sys", rtos.meminfo("sys"))
+-- end, 3000)
+
+
+-- 加载 json 应用模块
+require "json_app"
+
 
 -- 用户代码已结束---------------------------------------------
 -- 结尾总是这一句
 sys.run()
 -- sys.run()之后后面不要加任何语句!!!!!
-

+ 84 - 0
module/Air8101/demo/json/readme.md

@@ -0,0 +1,84 @@
+## 演示模块概述
+
+1、main.lua:主程序入口;
+
+2、json_app.lua:json 序列化与反序列化功能模块;
+
+## 演示功能概述
+
+使用 Air8101 核心板搭配 json 库演示 json 序列化与反序列化功能;
+
+演示分为两部分:
+
+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 的语义与比较行为说明:
+
+## 演示硬件环境
+
+1、Air8101 核心板一块
+
+2、TYPE-C USB数据线一根
+
+## 演示软件环境
+
+1、[Luatools下载调试工具](https://docs.openluat.com/air8000/luatos/common/download/)
+
+2、[Air8101 V1006 版本](https://docs.openluat.com/air8101/luatos/firmware/)(理论上最新版本固件也可以,如果使用最新版本的固件不可以,可以烧录 V1006-1 固件对比验证)
+
+## 演示核心步骤
+
+1、搭建好硬件环境
+
+2、Luatools 工具烧录内核固件和 demo 脚本代码
+
+3、烧录成功后,自动开机运行
+
+4、正常运行情况时的日志如下:
+
+```
+[00000001.009] I/user.string_string_test1 序列化成功: "test"
+[00000001.009] I/user.number_string_test1 序列化成功: 123456789
+[00000001.010] I/user.boolean_string_test1 序列化成功: true
+[00000001.010] I/user.table_string_test1 序列化成功: {"abc":123,"ttt":true,"def":"123"}
+[00000001.010] I/user.nil_string_test1 序列化成功:
+[00000001.011] I/user.table_string_test2 序列化失败: Cannot serialise function: type not supported
+[00000001.011] I/user.table_string_test3 序列化成功: {"abc":1234.568}
+[00000001.011] I/user.string_string_test1 反序列化成功: test
+[00000001.011] I/user.string_number_test1 反序列化成功: 123456789
+[00000001.011] I/user.string_boolean_test1 反序列化成功: true
+[00000001.011] I/user.string_table_test1.2 反序列化成功: table: 01FE5010
+[00000001.011] I/user.string_table_test1.2 反序列化成功: 1234545
+[00000001.011] I/user.string_table_test2 反序列化失败: Expected value but found T_OBJ_END at character 8
+[00000001.012] I/user.table_string_test3 序列化成功: {"abc":{}}
+[00000001.012] I/user.json 序列化成功: {"str":"ABC\r\nDEF\r\n"}
+[00000001.012] I/user.json 反序列化成功: ABC
+DEF
+ true
+[00000001.012] I/user.json.null {"name":null}
+[00000001.012] I/user.json.null true
+[00000001.012] I/user.json.null false
+```
+