json 解析的异常捕获

    代码执行错误日志如下:

    1. stack traceback:
    2. coroutine 0:
    3. [C]: in function 'decode'
    4. ...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 错误直接退了。改良了一下代码:

    1. local decode = require("cjson").decode
    2. function json_decode( str )
    3. local ok, t = pcall(decode, str)
    4. if not ok then
    5. return nil
    6. end
    7. end

    如果需要在 Lua 中处理错误,必须使用函数 pcall(protected call)来包装需要执行的代码。

    pcall 接收一个函数和要传递给那个函数的参数,并执行。

    接收的参数 (两个):

    • 第一个参数:被调用的函数,(可以是函数名或完整的函数体);
    • 第二个参数:传给被调用函数的参数。

    执行结果 (两种情况):

    • 有错误;
    • 无错误。

    返回值 (两个):

    • 第一个是 pcall 函数的运行状态:true 或者 ;
    • 第二个是被调用函数的返回值: 正常执行结果或者报错信息 (errorinfo)。

    示例

      1. local function foo(str)
      2. print("test pcall" .. str)
      3. return str
      4. end
      5. local str = 'hello'
      6. status, res = pcall(foo, str)
      7. print(status)
      8. print(res)

      执行结果:

      1. -- output:
      2. test pcall: hello
      3. true
      4. hello
    • 2、 发生错误的情况,test_pcall_bad.lua

      执行结果:

      1. -- output:
      2. 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

    1. local json = require("cjson.safe")
    2. local str = [[ {"key:"value"} ]] -- json 串中缺少一个双引号
    3. local t = json.decode(str)
    4. if t then
    5. end