JSON(JavaScript Object Notation)是一種輕量級的數據交換格式,廣泛應用於前後端數據交互,服務器消息推送、移動應用程序數據存儲等場景。在Lua中,我們使用json庫對JSON進行解析與序列化。json庫是由RapidJSON C++ 庫改寫的的C語言實現的json解析庫,可以在Lua與C/C++之間無縫兼容,極大地方便了在Lua環境下的JSON解析與序列化操作。
一、JSON基礎知識
JSON是一種輕量級的數據交換格式,在語法上與JavaScript中的對象字面量非常相似,這方便了Javascript中的JSON解析,同時也給了其他編程語言更廣泛的JSON解析工具。在JSON中,數據對象包含在一個花括號內,用逗號分隔。 在其中屬性-值對被稱為JSON對象,其中屬性用雙引號括起來,值可以是字符串、數字、邏輯值、數組或嵌套的JSON對象。
例如:
{ "name": "Alice", "age": 23, "gender": "female", "contacts": { "email": "alice@test.com", "phone": "1234567890" }, "hobbies": ["reading", "swimming", "travel"] }
二、使用Lua解析JSON
在Lua中,我們可以使用json庫對JSON進行解析,json庫是由RapidJSON C++ 庫改寫的C語言實現的JSON解析庫,支持UTF-8編碼。
在使用時,我們需要將json庫導入到我們的代碼中,例如:
local json = require "json"
然後使用`json.decode()`函數進行JSON字符串的解析,例如:
local str = '{"name":"Alice","age":23,"gender":"female","contacts":{"email":"alice@test.com","phone":"1234567890"},"hobbies":["reading","swimming","travel"]}' local data = json.decode(str)
則最終`data`的值為一個Lua對象,包含了JSON數據中的所有信息。
三、使用Lua對JSON進行序列化
除了解析JSON,我們還可以使用json庫將Lua對象序列化為JSON字符串。使用`json.encode()`函數進行序列化,例如:
local data = { name = "Alice", age = 23, gender = "female", contacts = { email = "alice@test.com", phone = "1234567890" }, hobbies = {"reading", "swimming", "travel"} } local str = json.encode(data)
則最終`str`的值為一個JSON字符串,與之前的JSON數據格式一致。
四、使用Lua編寫自己的JSON解析器
除了使用json庫解析JSON,我們也可以自己編寫一個簡單的JSON解析器,了解JSON的解析原理和實現方式。
在編寫JSON解析器時,我們可以將JSON數據看作一個樹形的數據結構,在解析的過程中,逐步地構建這個樹形結構,最終形成一個Lua對象。
例如:
local json = require "json" -- 解析JSON字符串 local function parse(jsonStr) local pos = 1 -- 當前解析到的位置 local len = string.len(jsonStr) -- JSON字符串的總長度 -- 解析一個值 local function parseValue() local ch = string.sub(jsonStr, pos, pos) if ch == "{" then -- 解析JSON對象 local obj = {} pos = pos + 1 ch = string.sub(jsonStr, pos, pos) while ch ~= "}" do if ch == '"' then -- 解析屬性名 pos = pos + 1 local key = parseString() pos = pos + 1 -- 跳過":"符號 obj[key] = parseValue() -- 遞歸解析屬性值 ch = string.sub(jsonStr, pos, pos) elseif ch == "," then -- 分隔符 pos = pos + 1 ch = string.sub(jsonStr, pos, pos) else error("unexpected char: " .. ch) end end pos = pos + 1 return obj elseif ch == "[" then -- 解析JSON數組 local arr = {} pos = pos + 1 ch = string.sub(jsonStr, pos, pos) local i = 1 while ch ~= "]" do arr[i] = parseValue() i = i + 1 ch = string.sub(jsonStr, pos, pos) end pos = pos + 1 return arr elseif ch == '"' then -- 解析JSON字符串 return parseString() elseif ch == "t" then -- 解析JSON布爾值true pos = pos + 4 return true elseif ch == "f" then -- 解析JSON布爾值false pos = pos + 5 return false elseif ch == "n" then -- 解析JSON空值null pos = pos + 4 return nil else -- 解析JSON數字 return parseNumber() end end -- 解析JSON字符串 local function parseString() local start = pos + 1 local find = string.find(jsonStr, '"', start) local endpos = find while true do if find == nil then error("miss double quote") end if string.sub(jsonStr, find-1, find-1) == "\\" then endpos = string.find(jsonStr, '"', endpos+1) else break end end pos = endpos return json.decode(string.sub(jsonStr, start, endpos)) end -- 解析JSON數字 local function parseNumber() local startpos = pos while true do local ch = string.sub(jsonStr, pos, pos) if ch >= "0" and ch <= "9" or ch == "+" or ch == "-" or ch == "e" or ch == "E" or ch == "." then pos = pos + 1 else break end end local endpos = pos - 1 return tonumber(string.sub(jsonStr, startpos, endpos)) end -- 解析JSON字符串 return parseValue() end local str = '{"name":"Alice","age":23,"gender":"female","contacts":{"email":"alice@test.com","phone":"1234567890"},"hobbies":["reading","swimming","travel"]}' local data = parse(str)
通過自己編寫JSON解析器的方式,我們可以更深度地理解JSON的解析原理,同時也能夠更好地掌握Lua的語法特性和函數使用方法。
五、總結
JSON是一種簡單、輕量級的數據交換格式,在前後端數據交互中有着廣泛的應用。在Lua中,我們可以使用json庫對JSON進行解析和序列化,也可以通過編寫自己的JSON解析器,更深入地理解JSON的解析原理和Lua語法特性。無論使用何種方式,掌握好JSON的解析和序列化操作都是成為一名優秀的Lua工程師必須掌握的技能之一。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/187853.html