<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh">
	<id>https://arolstar52-zhtest.hf.space/index.php?action=history&amp;feed=atom&amp;title=Module%3ASpecial_wikitext%2FJSON</id>
	<title>Module:Special wikitext/JSON - 版本历史</title>
	<link rel="self" type="application/atom+xml" href="https://arolstar52-zhtest.hf.space/index.php?action=history&amp;feed=atom&amp;title=Module%3ASpecial_wikitext%2FJSON"/>
	<link rel="alternate" type="text/html" href="https://arolstar52-zhtest.hf.space/index.php?title=Module:Special_wikitext/JSON&amp;action=history"/>
	<updated>2026-06-25T12:00:06Z</updated>
	<subtitle>在这个wiki上该页的修订历史</subtitle>
	<generator>MediaWiki 1.43.8</generator>
	<entry>
		<id>https://arolstar52-zhtest.hf.space/index.php?title=Module:Special_wikitext/JSON&amp;diff=3674710&amp;oldid=prev</id>
		<title>imported&gt;Xiplus-abot：​已更改“Module:Special wikitext/JSON”的保护设置：​高風險模板：392278引用&lt;!-- 機器人3 --&gt;（[编辑=仅允许管理员]（无限期）[移动=仅允许管理员]（无限期））</title>
		<link rel="alternate" type="text/html" href="https://arolstar52-zhtest.hf.space/index.php?title=Module:Special_wikitext/JSON&amp;diff=3674710&amp;oldid=prev"/>
		<updated>2024-01-17T21:24:17Z</updated>

		<summary type="html">&lt;p&gt;已更改“&lt;a href=&quot;/wiki/Module:Special_wikitext/JSON&quot; title=&quot;Module:Special wikitext/JSON&quot;&gt;Module:Special wikitext/JSON&lt;/a&gt;”的保护设置：​高風險模板：392278引用&amp;lt;!-- &lt;a href=&quot;/index.php?title=User:Xiplus-abot/task/3&amp;amp;action=edit&amp;amp;redlink=1&quot; class=&quot;new&quot; title=&quot;User:Xiplus-abot/task/3（页面不存在）&quot;&gt;機器人3&lt;/a&gt; --&amp;gt;（[编辑=仅允许管理员]（无限期）[移动=仅允许管理员]（无限期））&lt;/p&gt;
&lt;p&gt;&lt;b&gt;新页面&lt;/b&gt;&lt;/p&gt;&lt;div&gt;local p={}&lt;br /&gt;
local lib_arg={}&lt;br /&gt;
-- ======== 前處理器 ========&lt;br /&gt;
--由於技術限制，lua無法從mw.text.jsonDecode的回傳結果判斷物件、陣列與null因此定義一個$轉義符號來處理&lt;br /&gt;
function _preEsc(str)&lt;br /&gt;
	return mw.ustring.gsub(str,&amp;#039;%$&amp;#039;,&amp;quot;$$&amp;quot;)&lt;br /&gt;
end&lt;br /&gt;
function _postEsc(str)&lt;br /&gt;
	if not mw.ustring.find(tostring(str),&amp;#039;%$&amp;#039;) then return str end&lt;br /&gt;
	return mw.ustring.gsub(str,&amp;#039;%$%$&amp;#039;,&amp;quot;$&amp;quot;)&lt;br /&gt;
end&lt;br /&gt;
--處理HTML轉義符號&lt;br /&gt;
function _wikiescape(str)&lt;br /&gt;
	local escape_list = {&lt;br /&gt;
		{&amp;#039;#&amp;#039;,&amp;#039;&amp;amp;#35;&amp;#039;}, {&amp;#039;%{&amp;#039;,&amp;#039;&amp;amp;#123;&amp;#039;}, {&amp;#039;%|&amp;#039;,&amp;#039;&amp;amp;#124;&amp;#039;}, {&amp;#039;%}&amp;#039;,&amp;#039;&amp;amp;#125;&amp;#039;}, {&amp;#039;=&amp;#039;,&amp;#039;&amp;amp;#61;&amp;#039;}, {&amp;#039;:&amp;#039;,&amp;#039;&amp;amp;#58;&amp;#039;}, {&amp;#039;%[&amp;#039;,&amp;#039;&amp;amp;#91;&amp;#039;}, {&amp;#039;%]&amp;#039;,&amp;#039;&amp;amp;#93;&amp;#039;}&lt;br /&gt;
	}&lt;br /&gt;
	str = mw.text.encode( str )&lt;br /&gt;
	for i=1,#escape_list do str = mw.ustring.gsub(str,escape_list[i][1],escape_list[i][2]) end&lt;br /&gt;
	return str&lt;br /&gt;
end&lt;br /&gt;
--標記null物件&lt;br /&gt;
function _handleNull(input_string)&lt;br /&gt;
	local JSON_syms = &amp;quot;,:%[%]%{%}&amp;quot;&lt;br /&gt;
	local head_patterns,tail_patterns = {&amp;#039;^(%s*)&amp;#039;,&amp;#039;([&amp;#039;..JSON_syms..&amp;#039;]%s*)&amp;#039;},{&amp;#039;(%s*)$&amp;#039;,&amp;#039;(%s*[&amp;#039;..JSON_syms..&amp;#039;])&amp;#039;}&lt;br /&gt;
	local result = input_string&lt;br /&gt;
	for i=1,#head_patterns do&lt;br /&gt;
		for j=1,#tail_patterns do&lt;br /&gt;
			result = mw.ustring.gsub(result,head_patterns[i]..&amp;quot;null&amp;quot;..tail_patterns[j],function(head,tail)&lt;br /&gt;
				local p_head,p_tail = mw.text.trim(head),mw.text.trim(tail)&lt;br /&gt;
				local body = (p_tail==&amp;#039;:&amp;#039;and&amp;#039;&amp;#039;or&amp;#039;$&amp;#039;)..&amp;quot;null&amp;quot;&lt;br /&gt;
				return head..&amp;#039;&amp;quot;&amp;#039;..body..&amp;#039;&amp;quot;&amp;#039;..tail&lt;br /&gt;
			end)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return result&lt;br /&gt;
end&lt;br /&gt;
--標記陣列物件，令其與object物件區別&lt;br /&gt;
function _handleArray(input_string)&lt;br /&gt;
	local result = input_string&lt;br /&gt;
	result = mw.ustring.gsub(result,&amp;#039;%[&amp;#039;,&amp;#039;[&amp;quot;$array&amp;quot;,&amp;#039;)&lt;br /&gt;
	result = mw.ustring.gsub(result,&amp;quot;,%s*([%]%}])&amp;quot;,&amp;quot;%1&amp;quot;)&lt;br /&gt;
	return result&lt;br /&gt;
end&lt;br /&gt;
--將字串物件轉義，避免_handleArray過度標記&lt;br /&gt;
function _handleEscape(json_str)&lt;br /&gt;
	local result, json_stack = {}, {}&lt;br /&gt;
	local result_str = json_str&lt;br /&gt;
	xpcall(function() &lt;br /&gt;
		json_stack[#json_stack + 1]=mw.text.jsonDecode(json_str, mw.text.JSON_PRESERVE_KEYS + mw.text.JSON_TRY_FIXING)&lt;br /&gt;
		while(#json_stack &amp;gt; 0)do&lt;br /&gt;
			local top = json_stack[#json_stack]&lt;br /&gt;
			json_stack[#json_stack] = nil--pop&lt;br /&gt;
			if type(top) == type({}) then&lt;br /&gt;
				for k,v in pairs(top) do&lt;br /&gt;
					if type(k) == type(&amp;#039;&amp;#039;) then &lt;br /&gt;
						local esc_res = _wikiescape(k)&lt;br /&gt;
						if esc_res ~= k then&lt;br /&gt;
							result[#result + 1] = {k, _wikiescape(k)}&lt;br /&gt;
						end&lt;br /&gt;
					end&lt;br /&gt;
					json_stack[#json_stack + 1] = v&lt;br /&gt;
				end&lt;br /&gt;
			elseif type(top) == type(&amp;#039;&amp;#039;) then&lt;br /&gt;
				local esc_res = _wikiescape(top)&lt;br /&gt;
				if esc_res ~= top then&lt;br /&gt;
					result[#result + 1] = {top, _wikiescape(top)}&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		for i=1,#result do&lt;br /&gt;
			local pattern = &amp;#039;([\&amp;#039;&amp;quot;])&amp;#039;..mw.ustring.gsub(result[i][1],&amp;#039;([%%%(%)%[%]%{%}%|%$%^%+%-%*%.%?])&amp;#039;,&amp;#039;%%%1&amp;#039;)..&amp;#039;([\&amp;#039;&amp;quot;])&amp;#039;&lt;br /&gt;
			local replace_to = &amp;#039;%1&amp;#039;..mw.ustring.gsub(result[i][2],&amp;#039;%%&amp;#039;,&amp;#039;%%%%&amp;#039;)..&amp;#039;%2&amp;#039;&lt;br /&gt;
			result_str = mw.ustring.gsub(result_str, pattern, replace_to)&lt;br /&gt;
		end&lt;br /&gt;
	end,function() &lt;br /&gt;
		result = true&lt;br /&gt;
	end)&lt;br /&gt;
	if type(result) == type(true) then return result_str end&lt;br /&gt;
	return result_str&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- ======== 渲染器 ========&lt;br /&gt;
function _renderHide(value)&lt;br /&gt;
	return &amp;#039;&amp;lt;span class=&amp;quot;hidden-copyable&amp;quot;&amp;gt;&amp;#039;..value..&amp;#039;&amp;lt;/span&amp;gt;&amp;#039;&lt;br /&gt;
end&lt;br /&gt;
function _renderKeyString(value)&lt;br /&gt;
	return _renderHide(&amp;#039;&amp;quot;&amp;#039;).._wikiescape(value).._renderHide(&amp;#039;&amp;quot;&amp;#039;)&lt;br /&gt;
end&lt;br /&gt;
function _renderKey(value)&lt;br /&gt;
	return _renderKeyString(value).._renderHide(&amp;#039;:&amp;#039;)&lt;br /&gt;
end&lt;br /&gt;
function _rendeString(value)&lt;br /&gt;
	return &amp;#039;&amp;quot;&amp;#039;.._wikiescape(value)..&amp;#039;&amp;quot;&amp;#039;&lt;br /&gt;
end&lt;br /&gt;
function _rendeRawString(value)&lt;br /&gt;
	return _renderHide(&amp;#039;&amp;quot;&amp;#039;)..value.._renderHide(&amp;#039;&amp;quot;&amp;#039;)&lt;br /&gt;
end&lt;br /&gt;
function _rendeValue(value)&lt;br /&gt;
	if _isNumber(value) then return tostring(value)&lt;br /&gt;
	elseif type(value)==type(true) then return value and &amp;#039;true&amp;#039; or &amp;#039;false&amp;#039; &lt;br /&gt;
	elseif mw.ustring.find(value,&amp;quot;^%$null&amp;quot;) then return &amp;#039;null&amp;#039; &lt;br /&gt;
	elseif mw.ustring.find(value,&amp;quot;^%$array&amp;quot;) then return _rendeRawString(&amp;#039;&amp;lt;div class=&amp;quot;mw-json-empty&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;mw-json-empty-array&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&amp;#039;) &lt;br /&gt;
	elseif mw.ustring.find(value,&amp;quot;^%$reference&amp;quot;) then &lt;br /&gt;
		local s_strat, s_end = mw.ustring.find(value,&amp;quot;:&amp;quot;) &lt;br /&gt;
		local path = s_strat and mw.ustring.sub(value,s_strat+1,-1)&lt;br /&gt;
		return _rendeRawString(&amp;#039;&amp;lt;div class=&amp;quot;mw-json-reference&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;mw-json-reference-tag&amp;quot;&amp;gt;&amp;#039;..&lt;br /&gt;
			(path and(&amp;#039;[[#mw-json-ref-&amp;#039;..path..&amp;#039;|&amp;#039;..path..&amp;#039;]]&amp;#039;)or&amp;#039;&amp;#039;)..&amp;#039;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&amp;#039;)&lt;br /&gt;
	elseif mw.ustring.find(value,&amp;quot;^%$function&amp;quot;) then &lt;br /&gt;
		local s_strat, s_end = mw.ustring.find(value,&amp;quot;:&amp;quot;) &lt;br /&gt;
		return _rendeRawString(&amp;#039;&amp;lt;div class=&amp;quot;mw-json-function&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;mw-json-function-tag&amp;quot;&amp;gt;&amp;#039;..&lt;br /&gt;
		(s_strat and mw.ustring.sub(value,s_strat+1,-1) or &amp;#039;&amp;#039;)..&amp;#039;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&amp;#039;)&lt;br /&gt;
	elseif mw.ustring.find(value,&amp;quot;^%$error&amp;quot;) then &lt;br /&gt;
		local s_strat, s_end = mw.ustring.find(value,&amp;quot;:&amp;quot;) &lt;br /&gt;
		return _rendeRawString(&amp;#039;&amp;lt;div class=&amp;quot;mw-json-error&amp;quot;&amp;gt;&amp;lt;strong class=&amp;quot;error mw-json-error-tag&amp;quot;&amp;gt;&amp;#039;..&lt;br /&gt;
		(s_strat and mw.ustring.sub(value,s_strat+1,-1) or &amp;#039;&amp;#039;)..&amp;#039;&amp;lt;/strong&amp;gt;&amp;lt;/div&amp;gt;&amp;#039;)&lt;br /&gt;
	end&lt;br /&gt;
	return _rendeString(_postEsc(value))&lt;br /&gt;
end&lt;br /&gt;
function _renderTerminal(key, value, is_array, is_tail, sing_value)&lt;br /&gt;
	local body = &amp;#039;&amp;lt;tr&amp;gt;&amp;#039;&lt;br /&gt;
	..((key and not is_array) and (&amp;#039;&amp;lt;th&amp;gt;&amp;lt;span&amp;gt;&amp;#039;.._renderKey(key)..&amp;#039;&amp;lt;/span&amp;gt;&amp;lt;/th&amp;gt;&amp;#039;) or &amp;#039;&amp;#039;)&lt;br /&gt;
	..&amp;#039;&amp;lt;td&amp;#039;..(sing_value and&amp;#039;&amp;#039;or&amp;#039; class=&amp;quot;mw-json-value&amp;quot;&amp;#039;)..&amp;#039;&amp;gt;&amp;#039;.._rendeValue(value)..((not is_tail) and _renderHide(&amp;#039;,&amp;#039;) or &amp;#039;&amp;#039;)..&amp;#039;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;#039;&lt;br /&gt;
	return body&lt;br /&gt;
end&lt;br /&gt;
function _renderItem(key, item, is_array, is_tail)&lt;br /&gt;
	local body = &amp;#039;&amp;lt;tr&amp;gt;&amp;#039;&lt;br /&gt;
	..((key and not is_array) and (&amp;#039;&amp;lt;th&amp;gt;&amp;lt;span&amp;gt;&amp;#039;.._renderKey(key)..&amp;#039;&amp;lt;/span&amp;gt;&amp;lt;/th&amp;gt;&amp;#039;) or &amp;#039;&amp;#039;)&lt;br /&gt;
	..&amp;#039;&amp;lt;td&amp;gt;&amp;#039;..item..((not is_tail) and _renderHide(&amp;#039;,&amp;#039;) or &amp;#039;&amp;#039;)..&amp;#039;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;#039;&lt;br /&gt;
	return body&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- ======== 型態判斷工具 ========&lt;br /&gt;
function _isNumber(obj)&lt;br /&gt;
	if (tostring(obj):lower():match(&amp;quot;nan$&amp;quot;))==&amp;#039;nan&amp;#039; then return false end&lt;br /&gt;
	return tonumber(obj) ~= nil and tostring(tonumber(obj)) == tostring(obj)&lt;br /&gt;
end&lt;br /&gt;
function _isArray(obj)&lt;br /&gt;
	local min_val, max_val&lt;br /&gt;
	if obj == nil or type(obj) ~= type({}) then return false end&lt;br /&gt;
	if (obj[0] or &amp;#039;&amp;#039;) == &amp;#039;$array&amp;#039; then return true end&lt;br /&gt;
	for k,v in pairs(obj) do&lt;br /&gt;
		if _isNumber(k) then&lt;br /&gt;
			local key = tonumber(k)&lt;br /&gt;
			if min_val==nil then min_val = key end&lt;br /&gt;
			if max_val==nil then max_val = key end&lt;br /&gt;
			if min_val &amp;gt; key  then min_val = key end&lt;br /&gt;
			if max_val &amp;lt; key  then max_val = key end&lt;br /&gt;
		else return false end&lt;br /&gt;
	end&lt;br /&gt;
	return (min_val or -1) &amp;gt; 0 and #obj==(max_val or -1)&lt;br /&gt;
end&lt;br /&gt;
function _jsonDecode(str)&lt;br /&gt;
	local preJSON = _preEsc(str)&lt;br /&gt;
	preJSON = _handleEscape(preJSON)&lt;br /&gt;
	preJSON = _handleNull(preJSON)&lt;br /&gt;
	preJSON = _handleArray(preJSON)&lt;br /&gt;
	preJSON = mw.text.decode(preJSON)&lt;br /&gt;
	return mw.text.jsonDecode(preJSON, mw.text.JSON_PRESERVE_KEYS + mw.text.JSON_TRY_FIXING)&lt;br /&gt;
end&lt;br /&gt;
function p.JSONTable(frame)&lt;br /&gt;
	local json_data = mw.text.killMarkers( mw.text.unstripNoWiki( frame.args[1] or frame.args[&amp;#039;1&amp;#039;] or &amp;#039;&amp;#039; ) )&lt;br /&gt;
	local body = &amp;#039;&amp;#039;&lt;br /&gt;
	xpcall(function()&lt;br /&gt;
		body=p._json_reader(_jsonDecode(json_data))&lt;br /&gt;
	end,function(ex)&lt;br /&gt;
		local check_str = mw.ustring.gsub(json_data,&amp;quot;[\t\r\n\f%s,]+&amp;quot;,&amp;quot;&amp;quot;)&lt;br /&gt;
		local regex_check, show_code = mw.ustring.gsub(check_str,&amp;quot;^([%{%[].).*(.[%}%]])$&amp;quot;,&amp;quot;%1%2&amp;quot;)&lt;br /&gt;
		show_code = show_code &amp;gt; 0&lt;br /&gt;
		if mw.ustring.sub(regex_check,1,2)==&amp;quot;{{&amp;quot; then show_code = false end--物件中沒有key直接是物件絕對非法&lt;br /&gt;
		if show_code then&lt;br /&gt;
			mw.addWarning(&amp;quot;{{error|JSON解析器回傳錯誤：&amp;quot;..ex..&amp;quot;}}&amp;quot;)&lt;br /&gt;
			body = mw.getCurrentFrame():extensionTag{ name = &amp;#039;syntaxhighlight&amp;#039;, content = json_data, args = { lang = &amp;#039;json&amp;#039;, line = &amp;#039;line&amp;#039; } }&lt;br /&gt;
		else --明顯非法的json當作一般wikitext&lt;br /&gt;
			mw.addWarning(&amp;quot;{{error|錯誤，輸入的資料並非JSON}}，將以普通wikitext呈現。&amp;quot;)&lt;br /&gt;
			body = mw.getCurrentFrame():preprocess(mw.text.decode(json_data))&lt;br /&gt;
		end&lt;br /&gt;
	end)&lt;br /&gt;
	return body&lt;br /&gt;
end&lt;br /&gt;
--{{#invoke:Special wikitext/JSON|callAsJSON}}&lt;br /&gt;
function p.callAsJSON(...)&lt;br /&gt;
	local f_args = { ... }&lt;br /&gt;
    local in_args, working_frame&lt;br /&gt;
    local frame = f_args[1]&lt;br /&gt;
    if frame == mw.getCurrentFrame() then&lt;br /&gt;
        -- We&amp;#039;re being called via #invoke. The args are passed through to the module&lt;br /&gt;
        -- from the template page, so use the args that were passed into the template.&lt;br /&gt;
        if lib_arg.getArgs == nil then lib_arg = require(&amp;#039;Module:Arguments&amp;#039;) end&lt;br /&gt;
        in_args = lib_arg.getArgs(frame, {parentFirst=true})&lt;br /&gt;
        working_frame = frame&lt;br /&gt;
    else&lt;br /&gt;
        -- We&amp;#039;re being called from another module or from the debug console, so assume&lt;br /&gt;
        -- the args are passed in directly.&lt;br /&gt;
        in_args = frame&lt;br /&gt;
        working_frame = mw.getCurrentFrame()&lt;br /&gt;
        if type(in_args) ~= type({}) then &lt;br /&gt;
        	in_args = {} &lt;br /&gt;
        	for i=1,#f_args do&lt;br /&gt;
        		in_args[i] = f_args[i]&lt;br /&gt;
        	end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    local args = {}&lt;br /&gt;
    for k,v in pairs(in_args) do args[k]=v end&lt;br /&gt;
	local json_data, flag = mw.text.killMarkers( mw.text.unstripNoWiki( tostring(args[1] or args[&amp;#039;1&amp;#039;] or &amp;#039;&amp;#039;) ) )&lt;br /&gt;
	local path = mw.text.split(json_data,&amp;#039;%.&amp;#039;)&lt;br /&gt;
	if #path &amp;lt; 1 then return &amp;#039;&amp;#039; end&lt;br /&gt;
	local obj = _G[path[1]]&lt;br /&gt;
	if obj == nil then&lt;br /&gt;
		local file = mw.title.new(path[1], &amp;#039;module&amp;#039;)&lt;br /&gt;
		if file.exists then&lt;br /&gt;
			local contentModel = file.contentModel&lt;br /&gt;
			if contentModel == &amp;#039;scribunto&amp;#039; or contentModel == &amp;#039;lua&amp;#039; then&lt;br /&gt;
				flag,obj = pcall(require, file.fullText)&lt;br /&gt;
			elseif contentModel == &amp;#039;json&amp;#039; then&lt;br /&gt;
				flag,obj = pcall(mw.text.jsonDecode, file:getContent())&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if obj == nil then return &amp;#039;&amp;#039; end&lt;br /&gt;
	local get_arg = function(arg_list)&lt;br /&gt;
		local result_args = {}&lt;br /&gt;
		for j=2,#arg_list do&lt;br /&gt;
			local check_key = mw.text.trim(arg_list[j])&lt;br /&gt;
			if mw.ustring.sub(check_key,1,1)==&amp;#039;$&amp;#039; then&lt;br /&gt;
				local str_res,is_str = mw.ustring.gsub(check_key,&amp;quot;^%$string&amp;quot;,&amp;#039;&amp;#039;)&lt;br /&gt;
				local num_res,is_num = mw.ustring.gsub(check_key,&amp;quot;^%$number&amp;quot;,&amp;#039;&amp;#039;)&lt;br /&gt;
				if is_str &amp;gt; 0 then&lt;br /&gt;
					result_args[#result_args+1] = str_res&lt;br /&gt;
				elseif is_num &amp;gt; 0 then&lt;br /&gt;
					num_res = mw.ustring.lower(mw.text.trim(num_res))&lt;br /&gt;
					if num_res == &amp;#039;true&amp;#039; then result_args[#result_args+1] = true&lt;br /&gt;
					elseif num_res == &amp;#039;false&amp;#039; then result_args[#result_args+1] = false&lt;br /&gt;
					elseif tonumber(num_res)~=nil then result_args[#result_args+1] = tonumber(num_res)&lt;br /&gt;
					else result_args[#result_args+1] = num_res&lt;br /&gt;
					end&lt;br /&gt;
				end&lt;br /&gt;
			else result_args[#result_args+1] = arg_list[j]&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		return result_args&lt;br /&gt;
	end&lt;br /&gt;
	local target_obj = obj&lt;br /&gt;
	local old_obj = _G;&lt;br /&gt;
	local cur_path = path[1]&lt;br /&gt;
	local tmp_args = {}&lt;br /&gt;
	local no_call = false&lt;br /&gt;
	for i=2,#path do&lt;br /&gt;
		if i~=#path or path[i]~=&amp;#039;:&amp;#039; then &lt;br /&gt;
			if target_obj==nil then return p._json_reader(&amp;#039;$error: &amp;quot;&amp;#039;..cur_path..&amp;#039;&amp;quot; is nil.&amp;#039;) end&lt;br /&gt;
			local old_path = cur_path&lt;br /&gt;
			cur_path = old_path ..&amp;#039;.&amp;#039;.. path[i]&lt;br /&gt;
			if type(target_obj)==type(function()end) then &lt;br /&gt;
				local success_obj&lt;br /&gt;
				flag,success_obj = pcall(target_obj, unpack(tmp_args))&lt;br /&gt;
				if not success_obj or not flag then &lt;br /&gt;
					--try colon call&lt;br /&gt;
					flag,target_obj = pcall(target_obj, old_obj, unpack(tmp_args))&lt;br /&gt;
					if not target_obj or not flag then return p._json_reader(&amp;#039;$error: fail to get &amp;quot;&amp;#039;..cur_path..&amp;#039;&amp;quot; .&amp;#039;) end&lt;br /&gt;
				else target_obj = success_obj&lt;br /&gt;
				end&lt;br /&gt;
			elseif type(target_obj)~=type({}) then &lt;br /&gt;
				return p._json_reader(&amp;#039;$error: can not get &amp;quot;&amp;#039;..cur_path..&amp;#039;&amp;quot; from &amp;#039;..tostring(type(target_obj))..&amp;#039; value (&amp;#039;..old_path..&amp;#039;).&amp;#039;)&lt;br /&gt;
			end&lt;br /&gt;
			local cur_key = mw.text.split(path[i],&amp;#039;:&amp;#039;)&lt;br /&gt;
			tmp_args = get_arg(cur_key)&lt;br /&gt;
			local cur_obj_key = mw.text.trim(cur_key[1])&lt;br /&gt;
			if type(target_obj[cur_obj_key])~=type(function()end) then&lt;br /&gt;
				cur_obj_key = path[i]&lt;br /&gt;
			end&lt;br /&gt;
			old_obj = target_obj&lt;br /&gt;
			target_obj = target_obj[cur_obj_key]&lt;br /&gt;
		else&lt;br /&gt;
			no_call = true&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	local pack_data = {true,target_obj}&lt;br /&gt;
	if type(target_obj)==type(function()end) and not no_call then&lt;br /&gt;
		tmp_args = get_arg(args)&lt;br /&gt;
		pack_data = {pcall(target_obj, unpack(tmp_args))}&lt;br /&gt;
		local err_flag = pack_data[1]&lt;br /&gt;
		if not err_flag then &lt;br /&gt;
			local success_obj&lt;br /&gt;
			--try colon call&lt;br /&gt;
			success_obj = {pcall(target_obj, old_obj, unpack(tmp_args))}&lt;br /&gt;
			if not success_obj[1] then &lt;br /&gt;
				return p._json_reader(&amp;#039;$error: fail to call &amp;quot;&amp;#039;..cur_path..&amp;#039;&amp;quot; &amp;#039;..(pack_data[2] and (&amp;#039;, Message: &amp;#039;..pack_data[2]) or &amp;#039;&amp;#039;)..&amp;#039;.&amp;#039;) &lt;br /&gt;
			else pack_data = success_obj&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	local body_list = {}&lt;br /&gt;
	for i=2,#pack_data do&lt;br /&gt;
		local jsonlize&lt;br /&gt;
		local reference_list={}&lt;br /&gt;
		local target_unpack = pack_data[i]&lt;br /&gt;
		if target_unpack == nil then &lt;br /&gt;
			jsonlize = &amp;#039;$null&amp;#039;&lt;br /&gt;
		elseif type(target_unpack)==type(function()end) then&lt;br /&gt;
			jsonlize = &amp;#039;$function:&amp;#039;..cur_path&lt;br /&gt;
		elseif type(target_unpack)~=type({}) then&lt;br /&gt;
			jsonlize = _preEsc(tostring(target_unpack))&lt;br /&gt;
		else&lt;br /&gt;
			jsonlize,reference_list = p._table_copy(target_unpack)&lt;br /&gt;
		end&lt;br /&gt;
		body_list[#body_list+1]=p._json_reader(jsonlize, reference_list, (#pack_data&amp;gt;2)and&amp;#039;mw-json-multivalue&amp;#039;or nil)&lt;br /&gt;
	end&lt;br /&gt;
	if #body_list == 0 then return p._json_reader(&amp;#039;$null&amp;#039;)&lt;br /&gt;
	elseif #body_list == 1 then return body_list[1]&lt;br /&gt;
	else&lt;br /&gt;
		local body = &amp;#039;&amp;#039;&lt;br /&gt;
		for i=1,#body_list do&lt;br /&gt;
			if body ~= &amp;#039;&amp;#039; then body=body..&amp;#039;\n&amp;#039; end&lt;br /&gt;
			body = body..body_list[i]&lt;br /&gt;
		end&lt;br /&gt;
		return &amp;#039;&amp;lt;table class=&amp;quot;mw-json-multiple&amp;quot;&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;#039;.. body..&amp;#039;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&amp;#039;&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
function p._table_copy(json,target)&lt;br /&gt;
	local copy = {result=target or {}}&lt;br /&gt;
	local check_deep = {}&lt;br /&gt;
	local reference_list = {}&lt;br /&gt;
	local json_stack={{obj=json,target=copy,key=&amp;#039;result&amp;#039;,path=&amp;#039;root&amp;#039;}}&lt;br /&gt;
	while(#json_stack &amp;gt; 0)do&lt;br /&gt;
		local top = json_stack[#json_stack]&lt;br /&gt;
		json_stack[#json_stack] = nil--pop&lt;br /&gt;
		local topkey = _preEsc(top.key)&lt;br /&gt;
		if _isNumber(top.key) then topkey = tonumber(top.key) end&lt;br /&gt;
		if _isNumber(top.key) or type(top.key) == type(&amp;#039;&amp;#039;) then&lt;br /&gt;
			if type(top.obj) == type({}) then&lt;br /&gt;
				local is_same = false&lt;br /&gt;
				local cur_data&lt;br /&gt;
				for i=1,#check_deep do&lt;br /&gt;
					if check_deep[i].obj == top.obj then&lt;br /&gt;
						is_same = true&lt;br /&gt;
						cur_data = check_deep[i]&lt;br /&gt;
						break&lt;br /&gt;
					end&lt;br /&gt;
				end&lt;br /&gt;
				if not is_same then&lt;br /&gt;
					cur_data = {obj=top.obj, path=top.path..&amp;#039;.&amp;#039;..top.key}&lt;br /&gt;
					check_deep[#check_deep + 1] = cur_data&lt;br /&gt;
					top.target[topkey] = {}&lt;br /&gt;
					if top.obj[0]==nil and _isArray(top.obj)then&lt;br /&gt;
						top.target[topkey][0]=&amp;quot;$array&amp;quot;&lt;br /&gt;
					end&lt;br /&gt;
					for k,v in pairs(top.obj) do&lt;br /&gt;
						if type(k) ~= type({}) and type(k) ~= type(function()end) then&lt;br /&gt;
							json_stack[#json_stack + 1]={&lt;br /&gt;
								obj=v,&lt;br /&gt;
								target=top.target[topkey],&lt;br /&gt;
								key=_isNumber(k)and tonumber(k)or tostring(k),&lt;br /&gt;
								path=top.path..&amp;#039;.&amp;#039;..top.key&lt;br /&gt;
							}&lt;br /&gt;
						end&lt;br /&gt;
					end&lt;br /&gt;
				else&lt;br /&gt;
					local ref_path = mw.ustring.gsub(cur_data.path,&amp;#039;^root%.result%.&amp;#039;,&amp;#039;&amp;#039;)&lt;br /&gt;
					top.target[topkey] = &amp;#039;$reference:&amp;#039;..ref_path&lt;br /&gt;
					reference_list[ref_path] = true&lt;br /&gt;
				end&lt;br /&gt;
			elseif type(top.obj) == type(function()end) then&lt;br /&gt;
				top.target[topkey]=&amp;#039;$function:&amp;#039;..mw.ustring.gsub(top.path..&amp;#039;.&amp;#039;..top.key,&amp;#039;^root%.result%.&amp;#039;,&amp;#039;&amp;#039;)&lt;br /&gt;
			elseif type(top.obj) == type(&amp;#039;&amp;#039;) then&lt;br /&gt;
				if _isNumber(top.obj) then&lt;br /&gt;
					top.target[topkey]=tonumber(top.obj)&lt;br /&gt;
				else&lt;br /&gt;
					top.target[topkey]=_preEsc(top.obj)&lt;br /&gt;
				end&lt;br /&gt;
			else&lt;br /&gt;
				top.target[topkey]=top.obj&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return copy.result,reference_list&lt;br /&gt;
end&lt;br /&gt;
function p._json_reader(json,reference_list,other_class)&lt;br /&gt;
	local reference_list = reference_list or {}&lt;br /&gt;
	local sing_value = type(json) == type(&amp;#039;&amp;#039;) or type(json) == type(0) or type(json) == type(true)&lt;br /&gt;
	--見lua說明，遞迴的變數行為可能會導致遞迴失效，因此用堆疊實現&lt;br /&gt;
	local json_stack={{result=&amp;#039;&amp;#039;,obj={}}}&lt;br /&gt;
	json_stack[#json_stack + 1] = {obj=json,parent=json_stack[1],state=&amp;#039;start&amp;#039;,root=true,result=&amp;#039;&amp;#039;,is_last=true,path=&amp;#039;root&amp;#039;}&lt;br /&gt;
	while(#json_stack &amp;gt; 1)do&lt;br /&gt;
		local top = json_stack[#json_stack]&lt;br /&gt;
		if _isArray(top.obj) then&lt;br /&gt;
			if top.state == &amp;#039;start&amp;#039;then&lt;br /&gt;
				top.state = &amp;#039;process&amp;#039;&lt;br /&gt;
				top.cap = true&lt;br /&gt;
				local last_key&lt;br /&gt;
				for i=1,#top.obj do&lt;br /&gt;
					last_key = i&lt;br /&gt;
					json_stack[#json_stack + 1] = {&lt;br /&gt;
						obj = top.obj[i], key = i, parent=top, state=&amp;#039;start&amp;#039;,result=&amp;#039;&amp;#039;,type=&amp;#039;array_item&amp;#039;, path=top.path..&amp;#039;.&amp;#039;..(top.key or &amp;#039;result&amp;#039;)&lt;br /&gt;
					}&lt;br /&gt;
				end&lt;br /&gt;
				if last_key ~= nil then json_stack[#json_stack].is_last = true end&lt;br /&gt;
			elseif top.state == &amp;#039;process&amp;#039; then&lt;br /&gt;
				json_stack[#json_stack] = nil--pop&lt;br /&gt;
				local peek = top.parent&lt;br /&gt;
				local top_result = top.result&lt;br /&gt;
				if mw.text.trim(top_result) == &amp;#039;&amp;#039; then top_result =&amp;#039;&amp;lt;td class=&amp;quot;mw-json-empty&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;mw-json-empty-array&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/td&amp;gt;&amp;#039;end&lt;br /&gt;
				local result_data = _renderHide(&amp;#039;[&amp;#039;)..&amp;#039;&amp;lt;table class=&amp;quot;mw-json&amp;quot;&amp;gt;&amp;#039;..top_result..&amp;#039;&amp;lt;/table&amp;gt;&amp;#039;.. _renderHide(&amp;#039;]&amp;#039;)&lt;br /&gt;
				local is_array = top.key and not (top.type==&amp;#039;array_item&amp;#039;)&lt;br /&gt;
				result_data = _renderItem(_postEsc(top.key), result_data, top.type==&amp;#039;array_item&amp;#039;, top.is_last)&lt;br /&gt;
				peek.result=result_data..peek.result&lt;br /&gt;
			end&lt;br /&gt;
		elseif type(top.obj) == type({}) then&lt;br /&gt;
			if top.state == &amp;#039;start&amp;#039;then&lt;br /&gt;
				top.state = &amp;#039;process&amp;#039;&lt;br /&gt;
				top.cap = true&lt;br /&gt;
				local last_key&lt;br /&gt;
				for k,v in pairs(top.obj) do&lt;br /&gt;
					last_key = k&lt;br /&gt;
					json_stack[#json_stack + 1] = {&lt;br /&gt;
						obj = v, key = k, parent=top, state=&amp;#039;start&amp;#039;,result=&amp;#039;&amp;#039;,type=&amp;#039;obj_item&amp;#039;, path=top.path..&amp;#039;.&amp;#039;..(top.key or &amp;#039;result&amp;#039;)&lt;br /&gt;
					}&lt;br /&gt;
				end&lt;br /&gt;
				if last_key ~= nil then json_stack[#json_stack].is_last = true end&lt;br /&gt;
			elseif top.state == &amp;#039;process&amp;#039; then&lt;br /&gt;
				json_stack[#json_stack] = nil--pop&lt;br /&gt;
				local peek = top.parent&lt;br /&gt;
				local top_result = top.result&lt;br /&gt;
				local html_id = nil&lt;br /&gt;
				local ref_path = mw.ustring.gsub(top.path,&amp;#039;^root%.result%.&amp;#039;,&amp;#039;&amp;#039;)&lt;br /&gt;
				if reference_list[ref_path] == true then html_id=&amp;#039;mw-json-ref-&amp;#039;..ref_path end&lt;br /&gt;
				if mw.text.trim(top_result) == &amp;#039;&amp;#039; then top_result =&amp;#039;&amp;lt;td class=&amp;quot;mw-json-empty&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;mw-json-empty-object&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/td&amp;gt;&amp;#039;end&lt;br /&gt;
				local result_data = _renderHide(&amp;#039;{&amp;#039;)..&amp;#039;&amp;lt;table class=&amp;quot;mw-json&amp;quot;&amp;#039;..(html_id and (&amp;#039; id=&amp;quot;&amp;#039;..html_id..&amp;#039;&amp;quot;&amp;#039;)or&amp;#039;&amp;#039;)..&amp;#039;&amp;gt;&amp;#039;..top_result..&amp;#039;&amp;lt;/table&amp;gt;&amp;#039;.._renderHide(&amp;#039;}&amp;#039;)&lt;br /&gt;
				local is_array = top.key and not (top.type==&amp;#039;array_item&amp;#039;)&lt;br /&gt;
				local result_data = _renderItem(_postEsc(top.key), result_data, top.type==&amp;#039;array_item&amp;#039;, top.is_last)&lt;br /&gt;
				peek.result=result_data..peek.result&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			json_stack[#json_stack] = nil--pop&lt;br /&gt;
			local peek = top.parent&lt;br /&gt;
			local result_data = (type(top.obj) == type(0) or type(top.obj) == type(true) or type(top.obj) == type(&amp;#039;&amp;#039;))and &lt;br /&gt;
				_renderTerminal(_postEsc(top.key), top.obj, top.type==&amp;#039;array_item&amp;#039;, top.is_last, sing_value) or &amp;#039;&amp;#039;&lt;br /&gt;
			peek.result=top.result..result_data..peek.result&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	local class_list = {}&lt;br /&gt;
	if _isArray(json) or sing_value then class_list[#class_list+1]=&amp;quot;mw-json&amp;quot; end&lt;br /&gt;
	if sing_value then class_list[#class_list+1]=&amp;quot;mw-json-single-value&amp;quot; end&lt;br /&gt;
	if other_class then class_list[#class_list+1]=other_class end&lt;br /&gt;
	class_list = table.concat(class_list, &amp;#039; &amp;#039;)&lt;br /&gt;
	local outer_class = &amp;#039;class=&amp;quot;&amp;#039;..(class_list or &amp;#039;&amp;#039;).. &amp;#039; mw-json-main-table&amp;quot;&amp;#039;&lt;br /&gt;
	return &amp;#039;&amp;lt;table &amp;#039;..outer_class..&amp;#039;&amp;gt;&amp;#039; .. json_stack[1].result .. &amp;#039;&amp;lt;/table&amp;gt;&amp;#039;&lt;br /&gt;
end&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>imported&gt;Xiplus-abot</name></author>
	</entry>
</feed>