2 Licensed according to the included 'LICENSE' document
3 Author: Thomas Harning Jr <harningt@gmail.com>
5 local jsonutil
= require("json.util")
11 local table = require("table")
12 local math
= require("math")
13 local table_concat
= table.concat
14 local math_floor
, math_modf
= math
.floor, math
.modf
16 local jsonutil
= require("json.util")
17 local util_IsArray
= jsonutil
.IsArray
21 local defaultOptions
= {
22 isArray
= util_IsArray
25 local modeOptions
= {}
27 local function mergeOptions(options
, mode
)
28 jsonutil
.doOptionMerge(options
, false, 'array', defaultOptions
, mode
and modeOptions
[mode
])
32 Utility function to determine whether a table is an array or not.
33 Criteria for it being an array:
34 * ExternalIsArray returns true (or false directly reports not-array)
35 * If the table has an 'n' value that is an integer >= 1 then it
36 is an array... may result in false positives (should check some values
38 * It is a contiguous list of values with zero string-based keys
40 local function isArray(val
, options
)
41 local externalIsArray
= options
and options
.isArray
43 if externalIsArray
then
44 local ret
= externalIsArray(val
)
45 if ret
== true or ret
== false then
49 -- Use the 'n' element if it's a number
50 if type(val
.n
) == 'number' and math_floor(val
.n
) == val
.n
and val
.n
>= 1 then
54 for k
,v
in pairs(val
) do
55 if type(k
) ~= 'number' then
58 local _
, decim
= math_modf(k
)
59 if not (decim
== 0 and 1<=k
) then
62 if k
> len
then -- Use Lua's length as absolute determiner
71 Cleanup function to unmark a value as in the encoding process and return
74 local function unmarkAfterEncode(tab
, state
, ...)
75 state
.already_encoded
[tab
] = nil
78 local function getEncoder(options
)
79 options
= options
and jsonutil
.merge({}, defaultOptions
, options
) or defaultOptions
80 local function encodeArray(tab
, state
)
81 if not isArray(tab
, options
) then
84 -- Make sure this value hasn't been encoded yet
85 state
.check_unique(tab
)
86 local encode
= state
.encode
87 local compositeEncoder
= state
.outputEncoder
.composite
88 local valueEncoder
= [[
89 for i = 1, (composite.n or #composite) do
90 local val = composite[i]
92 val = encode(val, state)
99 return unmarkAfterEncode(tab
, state
, compositeEncoder(valueEncoder
, '[', ']', ',', tab
, encode
, state
))
101 return { table = encodeArray
}
105 mergeOptions
= mergeOptions
,
107 getEncoder
= getEncoder