local export = {}
local m_json = require("Module:JSON")

local function json_arrayFromTable_minified(val, converter)
	local ret = {}
	
	for i = 1, #val do
		elem = converter(val[i])
		if elem ~= nil then
			table.insert(ret, elem)
		end
	end
	
	return '[' .. table.concat(ret, ',') .. ']'
end

local function json_fromTable_minified(val, converter, sort_keys)
	local as_object = {}
	local string_key = false
	
	for key, value in (sort_keys and require "Module:table".sortedPairs or pairs)(val) do
		value = converter(value)
		
		if type(key) ~= "number" then
			string_key = true
		end
		
		if value ~= nil then
			key = m_json.json_fromString(tostring(key))
			table.insert(as_object, key .. ':' .. value)
		end
	end
	
	if string_key then
		return '{' .. table.concat(as_object, ',') .. '}'
	else
		return json_arrayFromTable_minified(val, converter)
	end
end

function export.toJSON(val, opts)
	opts = opts or {}
	
	local function converter(val)
		if type(val) == 'nil' then
			return 'null'
		elseif type(val) == 'boolean' then
			return val and 'true' or 'false'
		elseif type(val) == 'number' then
			return m_json.json_fromNumber(val)
		elseif type(val) == 'string' then
			return m_json.json_fromString(val)
		elseif type(val) == 'table' then
			-- If the table has a toJSON member function, call that.
			if val.toJSON then
				return val:toJSON()
			else
				return json_fromTable_minified(val, converter, opts.sort_keys)
			end
		else
			error('Unsupported type: ' .. type(val))
		end
	end
	
	return converter(val)
end

return export