使用Openresty中的cjson Lua模块解析缺少字段的JSON

使用Openresty中的cjson Lua模块解析缺少字段的JSON,json,nginx,lua,openresty,cjson,Json,Nginx,Lua,Openresty,Cjson,我试图解析通过POST请求发送到NGINX/Openrestylocation的json负载。为了做到这一点,我将Openresty与它结合起来,如下所示: # other locations above location /test { content_by_lua

我试图解析通过POST请求发送到NGINX/Openresty
location
的json负载。为了做到这一点,我将Openresty与它结合起来,如下所示:

# other locations above

location /test {                                                                                                               
    content_by_lua_block {                                                                                                 
        ngx.req.read_body()                                                                                            
        local data_string = ngx.req.get_body_data()                                                                    
                                                                                                                        
        local cjson = require "cjson.safe"                                                                             
        local json = cjson.decode(data_string)                                                                         
                                                                                                                        
        local endpoint_name = json['endpoint']['name']                                                             
        local payload = json['payload']                                                                            
        local source_address = json['source_address']                                                              
        local submit_date = json['submit_date']                                                                    
                                                                                                                            
        ngx.say('Parsed')                                                                                     
                                                                                                                            
    }                                                                                                                      
}                                                                                                               
{
    "payload": "the payload here",
    "submit_date": "2018-08-17 16:31:51",
    },
    "endpoint": {
        "name": "name of the endpoint here"
    },
    "source_address": "source address here",
}
解析包含所有必需字段的示例数据的工作方式与预期相同。正确的JSON对象可能如下所示:

# other locations above

location /test {                                                                                                               
    content_by_lua_block {                                                                                                 
        ngx.req.read_body()                                                                                            
        local data_string = ngx.req.get_body_data()                                                                    
                                                                                                                        
        local cjson = require "cjson.safe"                                                                             
        local json = cjson.decode(data_string)                                                                         
                                                                                                                        
        local endpoint_name = json['endpoint']['name']                                                             
        local payload = json['payload']                                                                            
        local source_address = json['source_address']                                                              
        local submit_date = json['submit_date']                                                                    
                                                                                                                            
        ngx.say('Parsed')                                                                                     
                                                                                                                            
    }                                                                                                                      
}                                                                                                               
{
    "payload": "the payload here",
    "submit_date": "2018-08-17 16:31:51",
    },
    "endpoint": {
        "name": "name of the endpoint here"
    },
    "source_address": "source address here",
}
但是,用户可能会将格式不同的JSON对象发布到
位置
。假设一个简单的JSON文档,如

{
    "username": "JohnDoe",
    "password": "password123"
}
不包含所需的字段/键

根据,如果遇到无效数据,则使用
cjson
(不带
安全
模式)将引发错误。为了防止出现任何错误,我决定通过导入
cjson.safe
来使用它的
safe
模式。对于无效数据,这应返回
nil
,并提供错误消息,而不是引发错误:

如果遇到任何无效数据,
cjson
模块将在JSON转换期间抛出错误。[……]

除了在JSON转换过程中遇到错误外,
cjson.safe
模块的行为与cjson模块相同。出现错误时,
cjson\u safe.encode
cjson\u safe.decode
功能将返回nil,然后返回错误消息

但是,在我的案例中,我没有遇到任何不同的错误处理行为,以下回溯显示在Openresty的
error.log
文件中:

2021/04/30 20:33:16[错误]6176#6176:*176 lua条目线程中止:运行时错误:内容由_lua(示例站点:50):16:尝试索引字段“端点”(零值)

从而导致内部服务器错误:

<html>                                                                                                                                 
<head><title>500 Internal Server Error</title></head>                                                                                  
<body>                                                                                                                                 
<center><h1>500 Internal Server Error</h1></center>                                                                                    
<hr><center>openresty</center>                                                                                                         
</body>                                                                                                                                
</html> 

500内部服务器错误
500内部服务器错误
openresty

我认为一种解决方法可能是编写一个专用函数来解析JSON数据,并使用
pcall()
调用它以捕获任何错误。但是,这会使
安全模式变得毫无用处。我在这里遗漏了什么?

您的“简单JSON文档”是一个有效的JSON文档。您面临的错误与cjson无关,它是一个标准Lua错误:

resty-e'localt={foo=1};印刷品(t[“foo”]);打印(t[“foo”][“bar”])'
1.
错误:(命令行-e):1:尝试索引字段“foo”(数值)
堆栈回溯:
...

cjson.safe的“安全性”是关于解析格式错误的文档:

  • cjson
    模块引发错误:

    resty-e'打印(需要(“cjson”)。解码([1,2,3”))
    错误:(命令行-e):1:应为逗号或数组结尾,但在字符9处找到T_结尾
    堆栈回溯:
    ...
    
  • cjson.safe
    返回
    nil
    和错误消息:

    resty-e'打印(需要(“cjson.safe”)。解码([1,2,3”))
    nill应为逗号或数组结尾,但在字符9处找到T_结尾
    

感谢您在此上下文中提供了一些详细信息。正如我昨天发现的,我的根本问题是试图访问一个嵌套表,其中第一级键为
nil
。因此,基本上我是在尝试访问
table[nil]['other_key']