nodemcu学习(四)-- json格式转化为table格式

这是我学的最糟糕的一个模块了, lua中的json形式的[] 和{} 转化为table是把我弄的头昏脑涨,   归结原因是对lua的语法不够明确,废话少说, 我们开始来今天的重点, 从json形式中提取我们想要的键或者键值.

华丽的分割线


lua中内置了一个json和table形式相互转化的模块--sjson模块

     sjson的官方api介绍在这:https://nodemcu.readthedocs.io/en/master/en/modules/sjson/#sjsondecoder

我们重点来说我们今天要用的api吧:sjson.decoder()

语法:sjson.decode(str[, opts])

参数: str: 需要转化的json字符串(注意是字符串), 一开始我没注意是字符串, 报错, 找了我含就                    好久才发现

             opts:选择可选的选项表。 可能的条目是:
                    深度编码表所需的最大编码深度。 默认值为20,几乎适用于所有情况。
                    null将字符串值视为null。
                     metatable一个表,用作返回对象中所有新表的元表。 请参阅上面                                               sjson.decoder()描述中的metatable部分

有这个函数就ok了, 开始我们的转换之旅吧.

首先要有一个json形式的字符串, 我就拿我上堂课在onenet平台上请求得到的一串数据拿来做实验吧:

sampleJson = '{"errno":0,"data":{"count":1,"datastreams":[{"datapoints":[{"at":"2018-10-17 12:45:49.000","value":34}],"id":"shidu_adjust"}]},"error":"succ"}';

这一个 json数据很复杂吧, 对于复杂结构的数据json数据 我们要理清谁是键, 谁又是键值, 而且还要理清, 那个json对象包含哪个对象, json对象中的{} 和[] 在这顺便补充一下吧, 在 JSON里[]是 Array(也就是数组),{}是Ojbect(也就是对象, 如果你想在一个键中包含多个json对象, 那么就得用数组形式

那么我们来分解这个json数据吧, 理清结构, 那如何进行分解呢?  这里介绍我的一种方法, 倘若有更好得方法, 我们可以互相讨论:

我主要是借助{} [] 和, 三个符号进行区分的,  先找到最外面的一对{}, 依次从左往右按照遇见在我们找的{}内而不在新出现的{}内的逗号就切开, 这句话有点拗口, 总而言之就是我们可以这样做: 找到最外层的一对{}后, 再找次外层的一对{}, 夹在最外层中不在次外层内的逗号切开, 第一次切后是下面这样的:

{
	 "errno":0,
	 "data":{"count":1,"datastreams":[{"datapoints":[{"at":"2018-10-17 12:45:49.000","value":34}],"id":"shidu_adjust"}]},
	 "error":"succ"
}

第二步呢: 就是把切完后的再切还有嵌套结构的json对象, 比如途中的data对象, 方法还是一样的, 切完后的结果如下:

{
	 "errno":0,
	 "data":{
	 		"count":1,
	 		"datastreams":[{"datapoints":[{"at":"2018-10-17 12:45:49.000","value":34}],"id":"shidu_adjust"}]
	 		},
	 "error":"succ"
 }

依次下去, 看到了[]号  不用怕, []表示是含有多个对象的json数组, 数组的元素用逗号隔开, 那么是不是和前面的类似了?, 下一步的:

{
	 "errno":0,
	 "data":{
	 		"count":1,
	 		"datastreams":[
	 					  {"datapoints":[{"at":"2018-10-17 12:45:49.000","value":34}],
	 					   "id":"shidu_adjust"}
	 					  ]
	 		},
	 "error":"succ"
	 }

再下一步:

{
	 "errno":0,
	 "data":{
	 		"count":1,
	 		"datastreams":[
	 					  {"datapoints":[
	 					  				{"at":"2018-10-17 12:45:49.000",
	 					  				 "value":34}
	 					  				],
	 					   "id":"shidu_adjust"}
	 					  ]
	 		},
	 "error":"succ"
	 }

 到此结构已经完全理清, 同学会问我, 理清这个有什么用, 我只想说用处可大了, 当你要查找某个键的键值的时候, 可以很快找出来.

来, 我们用api转化一下吧.:data = sjson.decode(sampleJson);顺便打印一下吧:print(data), 结果如下:

我的天, 打印的什么鬼东西, 我还是问问度娘吧, 度娘说, lua打印table对象时只会打印出table的内存地址,  这可怎么办.....  我想看打印的结果呢, 别急,  还有伟大的度娘呢, 找到一个打印table的脚本, 试试效果吧, 脚本代码:

function print_table ( t )  
    local print_r_cache={}
    local function sub_print_r(t,indent)
        if (print_r_cache[tostring(t)]) then
            print(indent.."*"..tostring(t))
        else
            print_r_cache[tostring(t)]=true
            if (type(t)=="table") then
                for pos,val in pairs(t) do
                    if (type(val)=="table") then
                        print(indent.."["..pos.."] => "..tostring(t).." {")
                        sub_print_r(val,indent..string.rep(" ",string.len(pos)+8))
                        print(indent..string.rep(" ",string.len(pos)+6).."}")
                    elseif (type(val)=="string") then
                        print(indent.."["..pos..'] => "'..val..'"')
                    else
                        print(indent.."["..pos.."] => "..tostring(val))
                    end
                end
            else
                print(indent..tostring(t))
            end
        end
    end
    if (type(t)=="table") then
        print(tostring(t).." {")
        sub_print_r(t,"  ")
        print("}")
    else
        sub_print_r(t,"  ")
    end
    print()
end

试试print_table(data), 结果如下:

table: 0x3fff0078 {
  [errno] => 0
  [data] => table: 0x3fff0078 {
              [count] => 1
              [datastreams] => table: 0x3fff0c20 {
                                 [1] => table: 0x3fff0dc8 {
                                          [id] => "shidu_adjust"
                                          [datapoints] => table: 0x3fff0220 {
                                                            [1] => table: 0x3fff0ea8 {
                                                                     [at] => "2018-10-17 12:45:49.000"
                                                                     [value] => 34
                                                                   }
                                                          }
                                        }
                               }
            }
  [error] => "succ"
}

小伙伴们, 是不是很惊奇, 这不是我们上面理清的那个结构吗, 只是多了table的地址还有[1], 我们惊奇的发现有[1]的地方刚好出现[], 奥...  那是应为[]是数组, 而[1]代表数组的第一个元素(lua的数组下标是从1开始的)我们来个最难的吧, 如果我们想打印value的值那应该怎么写? 思考一会, 等会放出答案
答案应该是: print(data["data"]["datastreams"][1]["datapoints"][1]["value"]) 来看看结果吧:

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

零涂

你的鼓励是我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值