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-hant/n/187853.html
微信掃一掃
支付寶掃一掃