Lua中嵌套数组的行为

问题描述

我有这段代码

json = require('dkjson')
dataStr = "{}"

function addEntry(position,hour,id)

        local data = json.decode(dataStr) or {} 
        
        if not data.detections then
            print("create data.detections")
            data.detections = {}
        end
        if not data.detections[position] then
            print("data.detections[position]")
            data.detections[position] = {}
        end              
        if not data.detections[position][hour] then
            print("data.detections[position][hour]")
            data.detections[position][hour] = {}
        end
        table.insert(data.detections[position][hour],id)
                
        dataStr = json.encode(data)
        print(dataStr)
end

addEntry("toto",28000,11111)
addEntry("toto",22222)
addEntry("toto",33333)
addEntry("toto",44444)
addEntry("toto",55555)

我在 Zerobrane 上有这个输出

create data.detections
create data.detections[position]
create data.detections[position][hour]
{"detections":{"toto":{"28000":[11111,11111]}}}
create data.detections[position][hour]
{"detections":{"toto":{"28000":[22222,22222],"28000":[11111,11111]}}}
create data.detections[position][hour]
{"detections":{"toto":{"28000":[33333,33333],11111]}}}
create data.detections[position][hour]
{"detections":{"toto":{"28000":[44444,44444],11111]}}}
create data.detections[position][hour]
{"detections":{"toto":{"28000":[55555,55555],11111]}}}

I would have expected to have this in the final string : 

```{"detections":{"toto":{"28000":[11111,22222,33333,44444,55555]}}}

Can somebody explain to me this Lua behavior ? The override instead of adding a new value,and this remaining separate first value ? 

解决方法

来自dkjson documentation

它也可以用来保存Lua数据结构,但是你应该 意识到并非每个 Lua 表都可以用 JSON 表示 标准。例如包含字符串键和一个 数组部分不能用 JSON 精确表示。

addEntry("toto",28000,11111)

印刷品

create data.detections
create data.detections[position]
create data.detections[position][hour]
{"detections":{"toto":{"28000":[11111,11111]}}}

您创建并编码了表格

{detections = {toto = {[28000] = {11111,11111}}}}

哪个给你 json 字符串

'{"detections":{"toto":{"28000":[11111,11111]}}}'

当你解码这个 json 字符串时,你会得到一个类似 lua 的表

{detections = {toto = {["28000"] = {11111,11111}}}}

正如你在解码后看到的 28000 现在是一个字符串键,而不是你编码的整数。

所以当你打电话

addEntry("toto",22222)

在这里,小时又是一个数字,你会得到表格

{detections = {toto = {[28000] = {22222,22222},["28000"] = {11111,11111}}}}

包含数字和字符串键的值。

如果你再次编码,你会得到 json 字符串

'{"detections":{"toto":{"28000":[22222,22222],"28000":[11111,11111]}}}'

现在我们再次解码,留下表格

{detections = {toto = {["28000"] = {11111,11111}}}}

因为第一个 "28000" 条目 {22222,22222} 当然被第二个 {11111,11111} 覆盖,因为我们不能有两个元素用于同一个键。

现在,您接下来的每个电话都会发生同样的事情。您添加了一个数字键并在编码/解码过程中丢失了它。

数字键仅在您的表是具有从 1 到 n 的连续整数键的序列时才使用。所有其他表键都转换为字符串。

双倍值是由于您这样做

 data.detections[position][hour] = {id}

data.detections[position][hour]nil 时,由于上述问题,在每次调用中都是如此。

当您在表中添加 id 之后,您最终会得到一个包含 id 两次的表。而是创建一个空表。