1. 程式人生 > >nodemcu學習(四)-- json格式轉化為table格式

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"]) 來看看結果吧: