在 Openresty 中使用 cjson Lua 模块解析缺少字段的 JSON
Parse JSON with missing fields using cjson Lua module in Openresty
我正在尝试解析通过 POST 请求发送到 NGINX/Openresty location
的 json 负载。为此,我将 Openresty 的 content_by_lua_block
with its cjson
module 组合成这样:
# 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')
}
}
解析包含所有必填字段的示例数据按预期工作。正确的 JSON 对象可能如下所示:
{
"payload": "the payload here",
"submit_date": "2018-08-17 16:31:51",
},
"endpoint": {
"name": "name of the endpoint here"
},
"source_address": "source address here",
}
但是,用户可能 POST 格式不同的 JSON 对象到 location
。假设一个简单的 JSON 文档,例如
{
"username": "JohnDoe",
"password": "password123"
}
不包含所需的 fields/keys。
根据 cjson
module docs,如果遇到无效数据,使用 cjson
(没有其 safe
模式)将引发错误。为了防止出现任何错误,我决定通过导入 cjson.safe
来使用它的 safe
模式。对于无效数据,这应该 return nil
并提供错误消息而不是引发错误:
The cjson
module will throw an error during JSON conversion if any invalid data is encountered. [...]
The cjson.safe
module behaves identically to the cjson module, except when errors are encountered during JSON conversion. On error, the cjson_safe.encode
and cjson_safe.decode
functions will return nil followed by the error message.
然而,在我的案例中我没有遇到任何不同的错误处理行为,以下回溯显示在 Openresty 的 error.log
文件中:
2021/04/30 20:33:16 [error] 6176#6176: *176 lua entry thread aborted: runtime error: content_by_lua(samplesite:50):16: attempt to index field 'endpoint' (a nil value)
这又会导致内部服务器错误:
<html>
<head><title>500 Internal Server Error</title></head>
<body>
<center><h1>500 Internal Server Error</h1></center>
<hr><center>openresty</center>
</body>
</html>
我认为解决方法可能是编写一个专用函数来解析 JSON 数据并使用 pcall()
调用它以捕获任何错误。但是,这会使 safe
模式有点无用。我在这里错过了什么?
您的“简单JSON文档”是有效JSON文档。您遇到的错误与 cjson
无关,它是标准 Lua 错误:
resty -e 'local t = {foo = 1}; print(t["foo"]); print(t["foo"]["bar"])'
1
ERROR: (command line -e):1: attempt to index field 'foo' (a number value)
stack traceback:
...
cjson.safe
的“安全性”是关于格式错误 文档的解析:
cjson
模块引发错误:
resty -e 'print(require("cjson").decode("[1, 2, 3"))'
ERROR: (command line -e):1: Expected comma or array end but found T_END at character 9
stack traceback:
...
cjson.safe
returns nil
和一条错误消息:
resty -e 'print(require("cjson.safe").decode("[1, 2, 3"))'
nilExpected comma or array end but found T_END at character 9
我正在尝试解析通过 POST 请求发送到 NGINX/Openresty location
的 json 负载。为此,我将 Openresty 的 content_by_lua_block
with its cjson
module 组合成这样:
# 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')
}
}
解析包含所有必填字段的示例数据按预期工作。正确的 JSON 对象可能如下所示:
{
"payload": "the payload here",
"submit_date": "2018-08-17 16:31:51",
},
"endpoint": {
"name": "name of the endpoint here"
},
"source_address": "source address here",
}
但是,用户可能 POST 格式不同的 JSON 对象到 location
。假设一个简单的 JSON 文档,例如
{
"username": "JohnDoe",
"password": "password123"
}
不包含所需的 fields/keys。
根据 cjson
module docs,如果遇到无效数据,使用 cjson
(没有其 safe
模式)将引发错误。为了防止出现任何错误,我决定通过导入 cjson.safe
来使用它的 safe
模式。对于无效数据,这应该 return nil
并提供错误消息而不是引发错误:
The
cjson
module will throw an error during JSON conversion if any invalid data is encountered. [...]The
cjson.safe
module behaves identically to the cjson module, except when errors are encountered during JSON conversion. On error, thecjson_safe.encode
andcjson_safe.decode
functions will return nil followed by the error message.
然而,在我的案例中我没有遇到任何不同的错误处理行为,以下回溯显示在 Openresty 的 error.log
文件中:
2021/04/30 20:33:16 [error] 6176#6176: *176 lua entry thread aborted: runtime error: content_by_lua(samplesite:50):16: attempt to index field 'endpoint' (a nil value)
这又会导致内部服务器错误:
<html>
<head><title>500 Internal Server Error</title></head>
<body>
<center><h1>500 Internal Server Error</h1></center>
<hr><center>openresty</center>
</body>
</html>
我认为解决方法可能是编写一个专用函数来解析 JSON 数据并使用 pcall()
调用它以捕获任何错误。但是,这会使 safe
模式有点无用。我在这里错过了什么?
您的“简单JSON文档”是有效JSON文档。您遇到的错误与 cjson
无关,它是标准 Lua 错误:
resty -e 'local t = {foo = 1}; print(t["foo"]); print(t["foo"]["bar"])'
1
ERROR: (command line -e):1: attempt to index field 'foo' (a number value)
stack traceback:
...
cjson.safe
的“安全性”是关于格式错误 文档的解析:
cjson
模块引发错误:resty -e 'print(require("cjson").decode("[1, 2, 3"))' ERROR: (command line -e):1: Expected comma or array end but found T_END at character 9 stack traceback: ...
cjson.safe
returnsnil
和一条错误消息:resty -e 'print(require("cjson.safe").decode("[1, 2, 3"))' nilExpected comma or array end but found T_END at character 9