JSON 数据的书写格式是:
key : value
JSON 值可以是:
JSON 解析器从本质上来说就是根据 JSON 文法规则创建的状态机
输入是一个 JSON 字符串,输出是一个Table。
具体代码实现
JsonLoader = {}
i = 1
json = ''
function JsonLoader:getChar(str, i)
--print(str, i)
return string.sub(str, i, i)
end
-- 跳过空格、换行、制表符、回车
function JsonLoader:skipWhitespace()
while (JsonLoader:getChar(json, i) == ' '
or JsonLoader:getChar(json, i) == '\n'
or JsonLoader:getChar(json, i) == '\t'
or JsonLoader:getChar(json, i) == '\r') do
i = i + 1
end
end
-- 处理逗号
function JsonLoader:eatComma()
if (JsonLoader:getChar(json, i) ~= ',') then
print('Expected ,')
end
i = i + 1
end
-- 处理冒号
function JsonLoader:eatColon()
if (JsonLoader:getChar(json, i) ~= ':') then
print('Expected :')
end
i = i + 1
end
-- 是否为16进制数
function JsonLoader:isHexadecimal(char)
return (char >= '0' and char <= '9') or (string.lower(char) >= 'a' and string.lower(char) <= 'f')
end
-- 获取字符串
function JsonLoader:parseString()
--print('parse String: ', i , 'times')
if (JsonLoader:getChar(json, i) == '"') then
i = i + 1
local result = ""
while (JsonLoader:getChar(json, i) ~= '"') do
if (JsonLoader:getChar(json, i) == '\\') then
char = JsonLoader:getChar(json, i+1)
if ( char == '"'
or char == '\\'
or char == '/'
or char == 'b'
or char == 'f'
or char == 'n'
or char == 'r'
or char == 't') then
result = result..char
i = i + 1
elseif (char == 'u') then
if (isHexadecimal(getChar(json, i+2))
and isHexadecimal(JsonLoader:getChar(json, i+3))
and isHexadecimal(JsonLoader:getChar(json, i+4))
and isHexadecimal(JsonLoader:getChar(json, i+5))) then
result = result .. string.sub(json,i+2, i+5)
i = i + 5
end
end
else
result = result .. JsonLoader:getChar(json, i)
-- 如果字符串为数字,进行转换
if tonumber(result) ~= nil then
result = tonumber(result)
end
end
i = i + 1
end
i = i + 1
--print("parse String res: ", result)
return result
end
return nil
end
-- 解析数值
function JsonLoader:parseNumber()
--print('parse Number: ', i , 'times')
start = i
if JsonLoader:getChar(json, i) == '-' then
i = i + 1
end
-- 解析数字,跳过首位0
if (JsonLoader:getChar(json, i) == '0') then
i = i +1
elseif (JsonLoader:getChar(json, i) >= '1' and JsonLoader:getChar(json, i) <= '9') then
i = i + 1
while(JsonLoader:getChar(json, i) >= '0' and JsonLoader:getChar(json, i) <= '9') do
i = i + 1
end
end
-- 检测小数
if(JsonLoader:getChar(json, i) == '.') then
i = i + 1
while(JsonLoader:getChar(json, i) >= '0' and JsonLoader:getChar(json, i) <= '9') do
i = i + 1
end
end
-- 检测科学计数法
if(JsonLoader:getChar(json, i) == 'e' or JsonLoader:getChar(json, i) == 'E') then
i = i + 1
if(JsonLoader:getChar(json, i) == '-' or JsonLoader:getChar(json, i) == '+') then
i = i + 1
end
while(JsonLoader:getChar(json, i) >= '0' and JsonLoader:getChar(json, i) <= '9') do
i = i + 1
end
end
if (i > start) then
--print('parse Number res: ', tonumber(string.sub(json, start, i-1)))
return tonumber(string.sub(json, start, i-1))
end
return nil
end
-- 解析关键字
function JsonLoader:parseKeyword(name, value)
if (string.sub(json, i, i + #name) == name) then
i = i + #name
return value
end
end
-- 解析对象
function JsonLoader:parseObject()
--print('parse Object: ', i , 'times')
if (JsonLoader:getChar(json, i)== '{') then
i = i + 1
JsonLoader:skipWhitespace()
local result = {}
initial = true
while (JsonLoader:getChar(json, i) ~= '}') do
if (not initial) then
JsonLoader:eatComma()
JsonLoader:skipWhitespace()
end
local key = JsonLoader:parseString()
JsonLoader:skipWhitespace()
JsonLoader:eatColon()
local value = JsonLoader:parseValue()
--print(key, value)
result[key] = value
initial = false
JsonLoader:skipWhitespace()
end
-- move to the next character of '}'
i = i + 1
--for k, v in pairs(result) do
-- print('202', k , v)
--
--end
--print('parse Object res: ', result)
return result
end
end
-- 解析值 递归调用其他方法
function JsonLoader:parseValue()
--print('parse Value: ', i , 'times')
JsonLoader:skipWhitespace()
local value
local string = JsonLoader:parseString()
local number = JsonLoader:parseNumber()
local object = JsonLoader:parseObject()
local array = JsonLoader:parseArray()
local tr = JsonLoader:parseKeyword('true', true)
local fl = JsonLoader:parseKeyword('false', false)
local ni = JsonLoader:parseKeyword('null', nil)
if string ~= nil then
return string
elseif number ~= nil then
return number
elseif object ~= nil then
return object
elseif array ~= nil then
return array
elseif tr == true then
return tr
elseif fl == false then
return fl
elseif ni == nil then
return ni
end
--local value = JsonLoader:parseString() or JsonLoader:parseNumber()
-- or JsonLoader:parseObject() or JsonLoader:parseKeyword('true', true)
-- or JsonLoader:parseKeyword('false', false) or JsonLoader:parseKeyword('null', nil)
JsonLoader:skipWhitespace()
--print('parse Value res:', value)
return value
end
-- 解析数组
function JsonLoader:parseArray()
--print('parse Array: ', i , 'times')
if (JsonLoader:getChar(json, i) == '[') then
i = i + 1
JsonLoader:skipWhitespace()
local result = {}
initial = true
while (JsonLoader:getChar(json, i) ~= ']') do
if (not initial) then
JsonLoader:eatComma()
end
local value = JsonLoader:parseValue()
table.insert(result, value)
initial = false
end
i = i + 1
return result
end
return nil
end
-- 解析主函数
function JsonLoader:parse(input_file)
print('start json parse')
--res = {}
--print(input_file)
-- 读取文件
local file = io.open(input_file, 'r')
json = file:read('*a')
file:close()
print(json)
-- json parse
--print(JsonLoader:getChar(json, i))
-- 判断首字符是否为'{'
if (JsonLoader:getChar(json, i) == '{') then
i = i + 1
JsonLoader:skipWhitespace()
-- 保存结果
local result = {}
initial = true
while (JsonLoader:getChar(json, i) ~= '}')
do
if not initial then
JsonLoader:eatComma()
JsonLoader:skipWhitespace()
end
local key = JsonLoader:parseString()
JsonLoader:skipWhitespace()
JsonLoader:eatColon()
local value = JsonLoader:parseValue()
--print("parse key- value: ",key, value)
result[key] = value
--print("273 res:", result[key])
JsonLoader:skipWhitespace()
initial = false
end
-- move to the next character '{'
i = i + 1
return result
end
return nil
end
input_file = 'a.json'
local mytable = JsonLoader.parse(nil, input_file)
print(' ---------------JsonLoader res -------------')
print(type(mytable))
print(mytable[1].a)
--[[
a.json
{"1":{"a":100}}
output:
table
100
]]--
JSON Parser with JavaScript