json 解析的异常捕获
代码执行错误日志如下:
stack traceback:
coroutine 0:
[C]: in function 'decode'
...ork/git/github.com/lua-resty-memcached-server/t/test.lua:8: in function <...ork/git/github.com/lua-resty-memcached-server/t/test.lua:1>, client: 127.0.0.1, server: localhost, request: "GET /test HTTP/1.1", host: "127.0.0.1:8001"
这可不是期望结果:decode 失败,500 错误直接退了。改良了一下代码:
local decode = require("cjson").decode
function json_decode( str )
local ok, t = pcall(decode, str)
if not ok then
return nil
end
end
如果需要在 Lua 中处理错误,必须使用函数 pcall
(protected call)来包装需要执行的代码。
pcall
接收一个函数和要传递给那个函数的参数,并执行。
接收的参数 (两个):
- 第一个参数:被调用的函数,(可以是函数名或完整的函数体);
- 第二个参数:传给被调用函数的参数。
执行结果 (两种情况):
- 有错误;
- 无错误。
返回值 (两个):
- 第一个是
pcall
函数的运行状态:true
或者 ; - 第二个是被调用函数的返回值: 正常执行结果或者报错信息 (
errorinfo
)。
示例
-
local function foo(str)
print("test pcall" .. str)
return str
end
local str = 'hello'
status, res = pcall(foo, str)
print(status)
print(res)
执行结果:
-- output:
test pcall: hello
true
hello
2、 发生错误的情况,
test_pcall_bad.lua
执行结果:
-- output:
test_pcall_bad.lua:2: attempt to concatenate global 'st' (a nil value)
pcall
以一种 “保护模式” 来调用第一个参数,因此 pcall
可以捕获函数执行中的任何错误。
通常在错误发生时,总希望可以得到更多的调试信息,而不只是发生错误的位置。但 pcall
返回时,它已经销毁了调用栈的部分内容。
cjson.safe 模块接口
另外,可以使用 CJSON 2.1.0
,该版本新增一个 cjson.safe
模块接口,该接口兼容 cjson
模块,并且在解析错误时不抛出异常,而是返回 nil
。
local json = require("cjson.safe")
local str = [[ {"key:"value"} ]] -- json 串中缺少一个双引号
local t = json.decode(str)
if t then
end