请教一个cjson的问题

842 views
Skip to first unread message

罗厚付

unread,
Mar 14, 2016, 11:46:40 PM3/14/16
to openresty
我想要处理json里能同时输出{},[]
当注释cjson.encode_empty_table_as_object(false)时
输出:{"NULL":null,"empty":"","data":3,"code":{},"specs":{}}
不注释时
输出:{"NULL":null,"empty":"","data":3,"code":[],"specs":[]}


lua代码
function Test()
   local cjson = require("cjson")
   cjson.encode_empty_table_as_object(false)
   local res1_body = cjson.decode('{"code":{},"specs":[],"empty":"","NULL":null,"data":1}')
   res1_body.data = 3
   local res = cjson.encode(res1_body)
   ngx.say(res)
end

请问有办法解决吗?

Guanglin Lv

unread,
Mar 15, 2016, 5:09:27 AM3/15/16
to openresty


在 2016年3月15日星期二 UTC+8上午11:46:40,罗厚付写道:
 json对象或数组都会被看为一张lua表,cjson并没有办法去标识这张表示来自对象还是数组。

 其它的库可能会有支持的,其中一个纯lua写的json库就支持这种严格类型转换: http://regex.info/code/JSON.lua

 
 

DeJiang Zhu

unread,
Mar 15, 2016, 6:30:38 AM3/15/16
to open...@googlegroups.com
Hello,

正巧,春哥今天合了一个 PR[1],正好是你要的
你可以使用这个 repo 的 master,或者等春哥的下一个发布版本


--
--
邮件来自列表“openresty”,专用于技术讨论!
订阅: 请发空白邮件到 openresty...@googlegroups.com
发言: 请发邮件到 open...@googlegroups.com
退订: 请发邮件至 openresty+...@googlegroups.com
归档: http://groups.google.com/group/openresty
官网: http://openresty.org/
仓库: https://github.com/agentzh/ngx_openresty
教程: http://openresty.org/download/agentzh-nginx-tutorials-zhcn.html

YuanSheng Wang

unread,
Mar 15, 2016, 10:48:58 AM3/15/16
to open...@googlegroups.com
我们曾经也被这个问题困扰过,原来还可以这么用。脑洞不够大开,看来自己要反省了。


--

YuanSheng Wang
---------------------------------------
OpenResty lover ^_^

Guanglin Lv

unread,
Mar 15, 2016, 8:43:25 PM3/15/16
to openresty

 赞~,虽然我还没遇到使用场景,不过先mark下~


在 2016年3月15日星期二 UTC+8下午6:30:38,doujiang写道:

罗厚付

unread,
Mar 15, 2016, 11:49:16 PM3/15/16
to openresty
再请教一下,这个具体要如何用。


在 2016年3月15日星期二 UTC+8下午6:30:38,doujiang写道:
Hello,

YuanSheng Wang

unread,
Mar 16, 2016, 12:08:09 AM3/16/16
to open...@googlegroups.com
2016-03-16 11:49 GMT+08:00 罗厚付 <luoh...@hotmail.com>:
> 再请教一下,这个具体要如何用。

+=== TEST 7: empty_array_mt and empty tables as objects (explicit)
+--- lua
+local cjson = require "cjson"
+cjson.encode_empty_table_as_object(true)
+local empty_arr = setmetatable({}, cjson.empty_array_mt)
+local data = {
+ arr = empty_arr,
+ foo = {
+ obj = {},
+ foobar = {
+ arr = cjson.empty_array,
+ obj = {}
+ }
+ }
+}
+print(cjson.encode(data))
+--- out
+{"foo":{"foobar":{"obj":{},"arr":[]},"obj":{}},"arr":[]}

罗厚付

unread,
Mar 16, 2016, 12:15:52 AM3/16/16
to openresty
  我对master分支进行make,替换掉openresty/lualib/cjson.so,并重启nginx 。
发现还是不能对字符串中的{}和[] 进行区别。

其实只要在encode时,能将[]识别为cjson.empty_array,这个问题就可以解决了。
还有人能解决这个问题吗?

在 2016年3月16日星期三 UTC+8上午11:49:16,罗厚付写道:

罗厚付

unread,
Mar 16, 2016, 12:19:49 AM3/16/16
to openresty
 我的这个业务场景是数据加工,把从其他接口(java)得到的json用lua进行序列化,然后再将多个接口的数据进行合并。最后再将数据用lua序列化输出。

在 2016年3月16日星期三 UTC+8下午12:08:09,YuanSheng写道:

kindy

unread,
Mar 16, 2016, 12:46:48 AM3/16/16
to open...@googlegroups.com
@罗,

这个fix 应该是不够完整的,
cjson.decode 貌似并没有将JSON string 中的 [] 标记为 empty_array (感觉上更应该标记为 as_array)。
所以当对 lua 对象进行 cjson.encode 的时候,因为原始信息丢失,导致 cjson 仍然无法区分 [] 和 {} 。

对于你的这个场景,cjson 应该还需要进一步的 fix 。

- - - - - - - - - - - -
林青(Kindy Lin)

lhmwzy

unread,
Mar 16, 2016, 1:30:04 AM3/16/16
to open...@googlegroups.com
没看明白楼主要干啥?

lhmwzy

unread,
Mar 16, 2016, 1:31:55 AM3/16/16
to open...@googlegroups.com
要输出这样的json吗?

lhmwzy

unread,
Mar 16, 2016, 1:32:17 AM3/16/16
to open...@googlegroups.com
{"code":{},"specs":[],"empty":"","NULL":null,"data":1}

类似于这样的?

罗厚付

unread,
Mar 16, 2016, 4:59:10 AM3/16/16
to openresty
是的,就是cjson.decode时,要能正确处理java接口输出的{},[],并正确的encode输出。

在 2016年3月16日星期三 UTC+8下午1:32:17,lhmwzy写道:

Ming

unread,
Mar 16, 2016, 5:10:05 AM3/16/16
to open...@googlegroups.com
lua里面没区分{}和[],春哥合并的pr只解决了encode的问题,并没有解决decode的问题。

Guanglin Lv

unread,
Mar 16, 2016, 5:54:52 AM3/16/16
to openresty


在 2016年3月16日星期三 UTC+8下午5:10:05,WenMing写道:
lua里面没区分{}和[],春哥合并的pr只解决了encode的问题,并没有解决decode的问题。

 decode出来的全都为lua表,我想用户自己应该知道表里哪个子项表示的是数组还是对象,在encode之前设置下对应的empty_array就行了呀; 


朱大仙儿

unread,
Mar 16, 2016, 5:56:38 AM3/16/16
to openresty
encode_empty_table_as_object

使用这个





------------------

朱大仙儿

手机:18513379185
微信号:wx23456346
QQ: 23456346

天脉聚源(北京)传媒科技有限公司/互动云研发部

北京市东城区安定门东大街雍和大厦E座8层

 
 
 
------------------ Original ------------------
From:  "Guanglin Lv"<guang...@gmail.com>;
Date:  Wed, Mar 16, 2016 05:54 PM
To:  "openresty"<open...@googlegroups.com>;
Subject:  Re: [openresty] 请教一个cjson的问题
 


在 2016年3月16日星期三 UTC+8下午5:10:05,WenMing写道:
lua里面没区分{}和[],春哥合并的pr只解决了encode的问题,并没有解决decode的问题。

 decode出来的全都为lua表,我想用户自己应该知道表里哪个子项表示的是数组还是对象,在encode之前设置下对应的empty_array就行了呀; 


朱大仙儿

unread,
Mar 16, 2016, 5:58:23 AM3/16/16
to openresty
function json_encode( data, empty_table_as_object )
  --Lua的数据类型里面,array和dict是同一个东西。对应到json encode的时候,就会有不同的判断
  --对于linux,我们用的是cjson库:A Lua table with only positive integer keys of type number will be encoded as a JSON array. All other tables will be encoded as a JSON object.
  --cjson对于空的table,就会被处理为object,也就是{}
  --dkjson默认对空table会处理为array,也就是[]
  --处理方法:对于cjson,使用encode_empty_table_as_object这个方法。文档里面没有,看源码
  --对于dkjson,需要设置meta信息。local a= {};a.s = {};a.b='中文';setmetatable(a.s,  { __jsontype = 'object' });ngx.say(comm.json_encode(a))

    local json_value = nil
    if json.encode_empty_table_as_object then
        json.encode_empty_table_as_object(empty_table_as_object or false) -- 空的table默认为array
    end
    if require("ffi").os ~= "Windows" then
        json.encode_sparse_array(true)
    end
    pcall(function (data) json_value = json.encode(data) end, data)
    return json_value
end





------------------

朱大仙儿

手机:18513379185
微信号:wx23456346
QQ: 23456346

天脉聚源(北京)传媒科技有限公司/互动云研发部

北京市东城区安定门东大街雍和大厦E座8层

 
 
 
------------------ Original ------------------
From:  "朱大仙儿"<zhuho...@tvmining.com>;
Date:  Wed, Mar 16, 2016 05:56 PM

Tonny Luo

unread,
Mar 18, 2016, 8:49:28 PM3/18/16
to openresty
我再仔细说下业务场景:

app -> openresty -> tomcat(多个)
openresty 负责将多tomcat输出的结果进行聚合。
在java中是严格区分对象{}和数组的,而在lua中用cjson进行decode时,是不能区分{}和[],现在就是询问能不能做到区分。
如果不能区分会导致 app 在对cjson.encode的结果进行反序列化时出错。比如android,也是java程序,那么就会严格区分{}和[],如果将{}反序列化为数组,这样就会引起crash。

当然你说的使用都应该知道json中哪个元素是数组,那个元素是对象。
但是lua中cjosn进行decode时没办法识别[]为数组,这样encode输出为{}会引起app crash。
如果使用cjson.encode_empty_table_as_object(false),这样{}就会被当成数组,同样也会引起app crash。

比较土的办法就是在java中将对象置为null输出。

当然希望lua中cjson.decode可以很好的识别{}和[]
懂c的朋友指导我一下,我自己来尝试改cjson ....

在 2016年3月16日星期三 UTC+8下午5:54:52,Guanglin Lv写道:

DeJiang Zhu

unread,
Mar 20, 2016, 9:27:16 PM3/20/16
to open...@googlegroups.com
Hello

其实楼上球哥 @kindy 已经说清楚了
decode 给 [] 加上 empty_table 这个metatable

Tonny Luo

unread,
Mar 21, 2016, 1:17:03 AM3/21/16
to openresty
请问具体要如何操作,我在下面这个链接也看到类似的问题。
https://github.com/mpx/lua-cjson/issues/11

在 2016年3月21日星期一 UTC+8上午9:27:16,doujiang写道:

武雅超

unread,
Jan 5, 2018, 10:40:29 AM1/5/18
to openresty
网关里面,接收的数据复杂且嵌套多层,用户是不知道的啊。所以还是需要decode的时候标记,貌似dkjson可以做到


在 2016年3月16日星期三 UTC+8下午5:54:52,Guanglin Lv写道:

Zexuan Luo

unread,
Jan 5, 2018, 9:41:22 PM1/5/18
to openresty
最新版的 openresty/lua-cjson 已经支持 decode 时标记了
https://github.com/openresty/lua-cjson/commits/master

在 2018年1月5日星期五 UTC+8下午11:40:29,武雅超写道:
Reply all
Reply to author
Forward
0 new messages