跳转至

json数据处理

一、JSON 介绍

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人类阅读和编写,同时也易于机器解析和生成。它基于 JavaScript 编程语言的一个子集,但独立于语言,广泛用于不同编程环境中。

1.1 JSON 的基本结构

1.1.1 对象

由花括号 {} 包围,包含键值对。键是字符串,值可以是字符串、数字、布尔值、数组、对象或 null。 { "name": "Alice", "age": 30, "isStudent": false }

1.1.2 数组

由方括号 [] 包围,包含一个有序的值列表。值可以是任何类型的数据,包括对象和其他数组。 [ "apple", "banana", "cherry" ]

1.2 JSON 的优点

简洁性:结构简单,易于理解和使用。

可移植性:语言无关,几乎所有的编程语言都支持 JSON 解析和生成。

灵活性:适用于各种数据结构的表示。

1.3 常用场景

Web 应用:用于客户端与服务器之间的数据交换。

配置文件:用于应用程序的配置设置。

数据存储:用于存储简单的数据结构。

综上所述,JSON 因其简单和灵活的特性,已经成为现代编程中数据交换的标准格式之一。

二、演示功能概述

本 demo 通过使用 Air8101 开发板,生成与解析 JSON 格式数据,并通过日志观察实验结果。

三、准备硬件环境

“古人云:‘工欲善其事,必先利其器。’在深入介绍本功能示例之前,我们首先需要确保以下硬件环境的准备工作已经完成。”

参考:硬件环境清单,准备以及组装好硬件环境。

四、软件环境

“凡事预则立,不预则废。”在详细阐述本功能示例之前,我们需先精心筹备好以下软件环境。

  1. Luatools 工具
  2. 内核固件文件(底层 core 固件文件):LuatOS-SoC_V10001_Air8101.soc;参考项目使用的内核固件
  3. luatos 需要的脚本和资源文件

脚本和资源文件:https://gitee.com/openLuat/LuatOS-Air8101/tree/master/demo/wlan/softAP

lib 脚本文件:使用 Luatools 烧录时,勾选 添加默认 lib 选项,使用默认 lib 脚本文件;

准备好软件环境之后,接下来查看如何烧录项目文件到 Air8101 开发板,将本篇文章中演示使用的项目文件烧录到 Air8101 开发板中。

五、API 介绍

5.1 json 编译

json.encode(torigin)

JSON 有自己规定的格式,一点的格式错误都无法 JSON 解析出有效数据。这里我们提供了 JSON 编译函数,你只需要把有效数据放入 table 类型的变量中,然后传入 JSON 编译函数 json.encode(table 类型变量),他就会返回 JSON 有效字符串。

参数

**参数**
**类型**
**释义**
**取值**
torigin
table
待编译的源字符

返回值

**返回值**
**类型**
**释义**
**取值**
res
string
json格式字符串

例子

local torigin =
{
    KEY1 = "VALUE1",
    KEY2 = "VALUE2",
    KEY3 = "VALUE3",
    KEY4 = "VALUE4",
    KEY5 = {KEY5_1="VALU5_1",KEY5_2="VALU5_2"},
    KEY6 = {1,2,3},
}

local jsondata = json.encode(torigin)

5.2 json 解析

json.decode(origin)

JSON 解析也很简单,有解析函数 json.decode(origin),origin 是待解析的 JSON 字符串。他会返回三个值(解析的内容,解析结果,错误信息)当 JSON 有效字符串被解析后,有效的数据就会被放在 table 的变量里,你需要定义一个变量接收一下。接着你就可以对 table 变量处理获取有效值。

参数

**参数**
**类型**
**释义**
**取值**
torigin
table
待解析的json字符串

返回值

**返回值**
**类型**
**释义**
**取值**
res
string
解析内容,table类型;解析结果,true为成功,false为失败;错误信息

例子

_-- 正确json字符串_local wrongOrigin = "{\":\"VALUE3\",\"KEY4\":\"VALUE4\",\"KEY2\":\"VALUE2\",\"KEY1\":\"VALUE1\",\"KEY5\":{\"KEY5_2\":\"VALU5_2\",\"KEY5_1\":\"VALU5_1\"},\"KEY6\":[1,2,3]}"local origin = "{\"KEY3\":\"VALUE3\",\"KEY4\":\"VALUE4\",\"KEY2\":\"VALUE2\",\"KEY1\":\"VALUE1\",\"KEY5\":{\"KEY5_2\":\"VALU5_2\",\"KEY5_1\":\"VALU5_1\"},\"KEY6\":[1,2,3]}"local tjsondata,result,errinfo = json.decode(origin)
if result thenprint(tjsondata["KEY1"])print(tjsondata["KEY2"])print(tjsondata["KEY3"])print(tjsondata["KEY4"])print(tjsondata["KEY5"]["KEY5_1"],tjsondata["KEY5"]["KEY5_2"])print(tjsondata["KEY6"][1],tjsondata["KEY6"][2],tjsondata["KEY6"][3])
elseprint("json.decode error",errinfo)
end

六、代码示例介绍

6.1 核心代码详解

6.1.1 将 Lua 表编码为 JSON 字符串

lua
local t = {abc=123, def="123", ttt=true}
local jdata = json.encode(t)
log.info("json", jdata)  -- 日志输出:{"ttt":true,"def":"123","abc":123}
  • 通过 json.encode(t) 将 Lua 表 t 转换为 JSON 字符串。
  • 输出的 JSON 字符串会在日志中显示。注意,JSON 的键值对顺序并不固定,可能与 Lua 表的顺序不同。

6.1.2 将 JSON 字符串解码为 Lua 表

lua
local str = "{\"abc\":1234545}"local t = json.decode(str)
if t thenlog.info("json", "decode", t.abc)  -- 日志输出:decode 1234545elselog.info("json", "decode failed")
end
  • json.decode(str) 尝试将 JSON 字符串转换为 Lua 表。如果转换成功,输出表中 abc 的值。如果失败,输出 "decode failed"。

6.1.3 混合类型表编码问题

lua
t.abc.def = "123"
t.abc[1] = 345log.info("json", "encode2", json.encode(t))  -- 日志输出:{"abc":{"1":345,"def":"123"}}
  • 这里的 t.abc 是一个混合类型的表,既包含了整数键 1,也包含了字符串键 def。编码后的 JSON 表示为对象而非数组,因为 JSON 对象是以键值对的形式表示数据。

6.1.4 浮点数编码

lua
log.info("json", json.encode({abc=1234.300}))  -- 日志输出:{"abc":1234.300}log.info("json", json.encode({abc=1234.300}, "1f"))  -- 日志输出:{"abc":1234.3}
  • json.encode 可以编码浮点数。在第二个例子中,使用 "1f" 参数将浮点数限制为最多一位小数。

6.1.5 特殊字符处理

lua
local tmp = "ABC\r\nDEF\r\n"local tmp2 = json.encode({str=tmp})
log.info("json", tmp2)  -- 日志输出:{"str":"ABC\r\nDEF\r\n"}
  • \r\n 是回车换行符,在 JSON 编码中,它会被保留作为字符串的一部分。
lua
local tmp3 = json.decode(tmp2)
log.info("json", "tmp3", tmp3.str, tmp3.str == tmp)  -- 日志输出:tmp3 ABC-- DEF-- true
  • 解码后的 JSON 字符串保持了原始的换行符,并且通过比较验证它们相等。

6.2 完整程序清单

注:完整复制后保存为 main.lua,可直接使用

-- main.lua文件
-- LuaTools需要PROJECT和VERSION这两个信息
PROJECT = "json_demo"
VERSION = "1.0.0"

-- sys库是标配
sys = require("sys")

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)

-- 用户代码已结束---------------------------------------------
-- 结尾总是这一句
sys.run()
-- sys.run()之后后面不要加任何语句!!!!!

七、功能验证

7.1 下载固件的基本设置

7.2 table 转为 字符串

7.3 字符串转 table

7.4 混合场景输出

7.5 浮点数演示

7.6 特殊字符处理

总结

至此,我们已使用 Air8101 开发板验证了 JSON 编、解码功能。