모듈:JSON: 두 판 사이의 차이

리버티게임(개발), 모두가 만들어가는 자유로운 게임
둘러보기로 이동 검색으로 이동
백괴게임>Gustmd7410
잔글편집 요약 없음
(사용자 지정 정렬이 가능한지 코드 추가)
 
(사용자 3명의 중간 판 30개는 보이지 않습니다)
13번째 줄: 13번째 줄:
Made by Gustmd7410 in Korean Ungame.
Made by Gustmd7410 in Korean Ungame.
]]--
]]--
local args = require('모듈:Arguments').getArgs
local a = {}
 
local b = setmetatable({
local p = {}
rtyp = a.typ,
local null = setmetatable({}, {
typ = false
__tostring = function()
}, {
return "null"
__index = a
end
})
})
 
local p = setmetatable({}, {
function decodeJSON(text)
__index = function(t, key)
if text:find('^%b{}$') or text:find('^%b[]$') then
return b[key] and function(frame)
local isArray = text:find('^%b[]$') and true
local args = getRawArgs(frame.args)
local obj = {}
local data = mw.text.jsonDecode(table.remove(args, 1))
local strings, objects, arrays = {}, {}, {}
local value = b[key](data, args)
local sindex, oindex, aindex = 1, 1, 1
text = text:sub(2, -2)
for value in text:gmatch('%b""') do
table.insert(strings, mw.text.jsonDecode(value))
end
for value in text:gmatch('%b{}') do
table.insert(objects, decodeJSON(value))
end
for value in text:gmatch('%b[]') do
table.insert(objects, decodeJSON(value))
end
text:gsub('%b""', '""')
text:gsub('%b{}', "{}")
text:gsub('%b[]', "[]")
for key, value in pairs(mw.text.split(text)) do
local entry = not isArray and mw.text.split(value, ":")
value = decodeJSON(isArray and value or entry[2])
if value == '""' then
if type(value) == "table"
value = strings[sindex]
then return mw.text.jsonEncode(value)
sindex = sindex + 1
else return value
elseif value == '{}' then
value = objects[oindex]
oindex = oindex + 1
elseif value == "[]" then
value = arrays[aindex]
aindex = aindex + 1
end
end
end or nil
if isArray
then table.insert(obj, value)
else obj[mw.text.jsonDecode(entry[1])] = value
end
end
return obj
elseif text == "null" then return null
else return mw.text.jsonDecode(text)
end
end
end
})
 
function getRawArgs(args)
function encodeJSON(obj, isArray)
local raw = {}
if obj == null then return "null"
elseif type(obj) == "table" then
for key, value in pairs(args) do
local text = ""
raw[key] = value
local index = 1
if isArray == nil then
for key in pairs(obj) do
if index == key then
index = index + 1
else isArray = false
end
end
isArray = not(isArray == false) and true
index = 1
end
for key, value in pairs(obj) do
if type(key) == "string" or type(key) == "number" then
if isArray then
if index == tonumber(key) then
text = text .. encodeJSON(value) .. ","
index = index + 1
end
else text = text .. mw.text.jsonEncode(tostring(key)) .. ":" .. encodeJSON(value) .. ","
end
end
end
if isArray
then return "[" .. text:sub(1, -2) .. "]"
else return "{" .. text:sub(1, -2) .. "}"
end
else return mw.text.jsonEncode(obj)
end
end
return raw
end
end


function settype(value)
function settype(value)
if pcall(mw.text.jsonDecode, value) then return mw.text.jsonDecode(value)
if value:find('^("+)(.*)%1$') and pcall(mw.text.jsonDecode, value:gsub('^("+)(.*)%1$', "%2")) then
elseif tonumber(value) then return tonumber(value)
return value:gsub('^"(("+)(.*)%2)"$', "%1")
elseif (value == 'true') then return true
elseif pcall(mw.text.jsonDecode, value) then return mw.text.jsonDecode(value)
elseif (value == 'false') then return false
elseif value == "" then return nil
elseif (value == 'null') then return null
else return value
elseif value:find('^"(("*)%2)"$') then return value:gsub('^"(("*)%2)"$', '%1')
elseif value:find('^"(("*)(%d+)%2)"$') then return value:gsub('^"(("*)(%d+)%2)"$', '%1')
elseif value:find('^"(("*)(true)%2)"$') then return value:gsub('^"(("*)(true)%2)"$', '%1')
elseif value:find('^"(("*)(false)%2)"$') then return value:gsub('^"(("*)(false)%2)"$', '%1')
elseif value:find('^"(("*)(null)%2)"$') then return value:gsub('^"(("*)(null)%2)"$', '%1') 
else return value
end
end
end
end
130번째 줄: 56번째 줄:
local key = frame.args[2]
local key = frame.args[2]
key = tonumber(key) or key
key = tonumber(key) or key
local value = mw.text.jsonDecode(frame.args[1])[key]
return type(mw.text.decodeJSON(frame.args[1])[key])
if value == null then return "null" end
return type(value)
end
end


function p.rtyp(frame)
function a.typ(data)
return type(mw.text.decodeJSON(frame.args[1]))
return type(data)
end
end


function p.get(frame)
function a.get(data, args)
local key = frame.args[2]
for depth, key in pairs(args) do
key = tonumber(key) or key
key = tonumber(key) or key
data = data[key]
end
local value = mw.text.jsonDecode(frame.args[1])[key]
return data
return (type(value) == 'table') and mw.text.jsonEncode(value) or value
end
end


function p.set(frame)
function a.set(data, args)
local data = mw.text.jsonDecode(frame.args[1])
local key = args[1]
local key = frame.args[2]
local value = mw.text.trim(args[2])
local value = mw.text.trim(frame.args[3])
key = tonumber(key) or key
key = tonumber(key) or key
data[key] = settype(value)
data[key] = settype(value)
return mw.text.jsonEncode(data)
return data
end
end


function p.new(frame)
function p.new(frame)
local data = args(frame)
local data = getRawArgs(frame.args)
for key in pairs(data) do data[key] = settype(mw.text.trim(data[key])) end
for key, value in pairs(data) do
data[key] = settype(mw.text.trim(value))
end
return mw.text.jsonEncode(data)
return mw.text.jsonEncode(data)
end
end


function p.mer(frame)
function a.mer(base, args)
local base = mw.text.jsonDecode(frame.args[1])
for seq in pairs(args) do
local data = mw.text.jsonDecode(args[seq])
for key in pairs(data) do base[key] = data[key] end
end
return base
end


for seq in pairs(args(frame)) do
function a.del(data, args)
if not(seq == 1) then
for seq, key in pairs(args) do
local data = mw.text.jsonDecode(frame.args[seq])
data[tonumber(key) or key] = nil
for key in pairs(data) do base[key] = data[key] end
end
end
end
return mw.text.jsonEncode(base)
return data
end
end


function p.del(frame)
function a.len(data)
local data = mw.text.jsonDecode(frame.args[1])
return #data
end
 
function a.con(data, args)
return table.concat(data, args[2] or ',', tonumber(args[3]) or 1, tonumber(args[4]) or #data)
end
 
function a.ins(data, args)
local index = tonumber(args[3]) or #data + 1
if index < 0 then
index = #data + index
end
for seq in pairs(args(frame)) do
table.insert(data, index, args[2])
if not(seq == 1) then
return data
local key = tonumber(frame.args[seq]) or frame.args[seq]
end
 
data[key] = nil
function a.rem(data, args)
for seq, key in pairs(args) do
key = tonumber(key)
if key < 0 then
key = #data + key
end
end
table.remove(data, key)
end
end
return mw.text.jsonEncode(data)
return data
end
 
function a.srt(data, args)
table.sort(data)
return data
end
 
function a.srt_custom(data, args)
table.sort(data, args[1])
return data
end
 
function p.chk(frame)
if pcall(mw.text.jsonDecode, frame.args[1])
then return frame.args[2]
else return frame.args[3]
end
end
end


function p.len(frame)
function p.str(frame)
return #mw.text.jsonDecode(frame.args[1])
return mw.text.jsonDecode('"' .. frame.args[1] .. '"')
end
end


function p.con(frame)
function p.pty(frame)
local data = mw.text.jsonDecode(frame.args[1])
local data = mw.text.jsonDecode(frame.args[1])
return table.concat(data, frame.args[2], tonumber(frame.args[3]) or 1, tonumber(frame.args[4]) or #data)
return mw.text.jsonEncode(data, mw.text.JSON_PRETTY)
end
end


function p.ins(frame)
function p.cmd(frame)
local data = mw.text.jsonDecode(frame.args[1])
local data = mw.text.jsonDecode(frame.args[1])
local commands = mw.text.jsonDecode('[' .. frame.args[2]:sub(1, -2) .. ']')
local pretty = false
table.insert(data, tonumber(frame.args[3]) or #data + 1, frame.args[2])
for index, command in pairs(commands) do
for action, args in pairs(command) do
if action == 'pty' then
pretty = true
else
data = a[action](data, args)
end
break
end
end
if type(data) == "table" then
return pretty and mw.text.jsonEncode(data, mw.text.JSON_PRETTY) or mw.text.jsonEncode(data)
else
return data
end
end
 
function a.has(data, args)
local valt = {}
local result = nil
return mw.text.jsonEncode(data)
for key, value in pairs(data) do
valt[value] = true
end
for index, value in pairs(args) do
if result == nil then result = true end
if valt[value] ~= true then result = false end
end
return result
end
end


function p.rem(frame)
a['for'] = function(data, args)
local data = mw.text.jsonDecode(frame.args[1])
local text = ''
local keyv = args.key or 'key'
local valv = args.value or 'value'
local func = require('모듈:TemplateFunction').new(args[1])
for seq in pairs(args(frame)) do
for key, value in pairs(data) do
if not(seq == 1) then
if type(value) == "table" then
table.remove(data, tonumber(frame.args[seq]))
value = mw.text.jsonEncode(value)
end
end
text = text .. func{
[keyv] = key,
[valv] = value
}
end
end
return mw.text.jsonEncode(data)
return text
end
end


function p.srt(frame)
function a.map(data, args)
local data = mw.text.jsonDecode(frame.args[1])
local keyv = args.key or 'key'
local valv = args.value or 'value'
local func = require('모듈:TemplateFunction').new(args[1])
table.sort(data)
for key, value in pairs(data) do
if type(value) == "table" then
value = mw.text.jsonEncode(value)
end
data[key] = settype(func{
[keyv] = key,
[valv] = value
})
end
return mw.text.jsonEncode(data)
return data
end
end


function p.chk(frame)
function a.red(data, args)
if pcall(mw.text.jsonDecode, frame.args[1])
local val = ''
then return frame.args[2]
local keyv = args.key or 'key'
else return frame.args[3]
local valv = args.value or 'value'
local prev = args.previous or 'previous'
local func = require('모듈:TemplateFunction').new(args[1])
for key, value in pairs(data) do
if type(value) == "table" then
value = mw.text.jsonEncode(value)
end
val = func{
[keyv] = key,
[valv] = value,
[prev] = val
}
end
end
return val
end
end


function p.str(frame)
function p.spl(frame)
return mw.text.jsonDecode('"' .. frame.args[1] .. '"')
local text = frame.args[1]
local sep = frame.args[2]
return mw.text.jsonEncode(mw.text.split(text, sep))
end
end
p.null = null
p.decode = decodeJSON
p.encode = encodeJSON


return p
return p

2024년 9월 30일 (월) 15:28 기준 최신판


모듈 설명문서[보기] [편집] [역사] [새로 고침]

JSON 데이터를 읽어들여 값을 반환하거나, 데이터를 수정합니다.

주의사항

이 모듈은 null을 없는 값으로 간주합니다. 따라서 null 값을 보존하려면 이 모듈을 사용하지 말것을 권장합니다.

사용전:
{"var1": true, "var2": null, "var3": false}

사용후:
{"var1": true, "var3": false}

루아에서는 배열의 순서가 1부터 시작합니다. 이 점 유의해 주세요.

["aaa", "bbb", "ccc", "ddd"]
JS Lua
0 aaa 1
1 bbb 2
2 ccc 3
3 ddd 4

객체의 경우 속성이 표시되는 순서가 바뀔 수 있습니다. 단, 배열은 해당되지 않으며 객체의 순서가 바뀌어도 속성명은 변하지 않으므로 변수를 호출할 때에 큰 문제는 없습니다.

사용전:
{"var1": "aaaa", "var2": 1234, "var3": true}
[1, 3, 5, 9]

사용후:
{"var2":1234,"var3":true,"var1":"aaaa"}
[1,3,5,9]

사용법

변수

객체를 사용한다면 속성명을 그대로 입력하시면 됩니다.

JSON에서는 문자열, 숫자, 부울, 배열, 객체, null을 다루며, 이 틀에서 값을 입력할 때 기본적으로는 문자열으로 처리되지만, JSON 값의 형식에 맞춰서 입력한다면 자동으로 타입이 적용됩니다. 만약 강제적으로 문자열을 적용하고 싶다면 ""로 이스케이프하실 수 있습니다. 만약, 이스케이프된 문자열을 ""로 묶고 싶으시다면 그 안에 ""를 더 넣으실 수 있습니다. (예시: "true"true, ""123"""123")

칸을 비우시면 없는 값으로 간주되어 내용이 삭제됩니다. 만약, 빈 문자열을 사용하고 싶으시다면 ""을 입력하세요. 칸을 비우기 곤란하시다면 null을 사용하여 내용을 지우실 수 있습니다. null 역시 마찬가지로 "null"과 같이 이스케이프가 가능합니다.

JSON 코드

조작할 JSON 데이터를 특정합니다. 상황에 따라 다음 중 한가지 방법대로 두번째 변수(JSON 코드)에 입력해 주세요.

  • JSON 코드 직접 입력
JSON 코드가 반환되는 이 모듈도 사용하실 수 있습니다.
  • JSON 문서 불러오기
JSON 문서를 불러와서 입력하시려면 다음과 같이 틀의 형태로 입력해 주세요.
{{사용자:홍길동/데이터.json}}
{{:한게임/DB}}
  • 빈 JSON 코드
비어있는 JSON 코드를 사용하시려면 {}[]만 입력해 주세요.

새로 만들기

{{#switch:}}문법과 비슷하게 JSON 데이터를 새로 만들 수 있습니다.

{{#invoke:JSON|new|(값1)|(변수a)=(값a)|...}}

변수를 지정하지 않은 경우 변수는 틀과 같이 순서로 지정이 되며, 배열을 만들고자 할 경우 변수 없이 값만 입력하시면 됩니다.

이 기능은 앞서 말했다시피 #switch 문법과 유사하기 때문에 호환이 될 수 있습니다. 앞부분의 {{#switch:{{{1}}}부분을 한번 {{풀기:#invoke:JSON|new로 변경해 보세요. switch가 JSON으로 마법같이 변신할겁니다.

{{#switch:{{{1}}}
|var1=aaaa
|var2=1234
|var3=true
}}
{{풀기:#invoke:JSON|new
|var1=aaaa
|var2=1234
|var3=true
}}
{
	"var2": 1234,
	"var3": true,
	"var1": "aaaa"
}

어때요, 신기하지 않나요? 이 기능과 함께 switch에서 JSON으로 갈아타세요!

다른 방법으로, 일반 문자열을 콤마(,) 등을 기준으로 나눠서 배열을 만들 수 있습니다.

{{#invoke:JSON|spl|(문자열)|(구분자)}}

구분자를 비우거나 입력하지 않으면 기본적으로 글자 하나하나씩 나눕니다.

여기서 주의할 점은 구분자는 일반 문자열이 아니라 정규 표현식과 비슷한 패턴으로 입력해야 한다는 겁니다. 루아의 패턴 문법(영문)을 참고해서 입력해 주세요.

변수값 얻기

JSON 데이터에 있는 변수의 값을 얻으려면 다음과 같이 입력합니다:

{{#invoke:JSON|get|(JSON 코드)|(변수)}}

위와 같이 입력하시면 해당 변수의 값만 그대로 나오며, 값이 없는 경우 기본값이 나옵니다.

예를 들어, var 변수의 값을 얻는다면 이렇게 입력하세요:

{{#invoke:JSON|get|(JSON 코드)|var}}

{{JSON}}을 이용하면 더 간단히 입력하실 수 있습니다. 자세한 내용은 해당 문서를 확인해 주세요.

변수값 변경

JSON 데이터에 있는 변수의 값을 변경하려면 다음과 같이 입력합니다:

{{#invoke:JSON|set|(JSON 코드)|(변수)|(값)}}

위와 같이 입력하시면 해당 변수의 값이 변경된 JSON 코드가 반환됩니다.

예를 들어, var 변수의 값을 6로 변경할 경우 이렇게 입력하세요:

{{#invoke:JSON|set|(JSON 코드)|var|6}}

JSON 데이터에 없는 변수를 추가할때도 마찬가지로 똑같이 입력하시면 됩니다.

변수의 값을 비워두거나 null로 설정하면 변수가 제거됩니다.

코드 합치기

두 JSON 코드를 합칩니다. new랑 궁합이 매우 좋습니다.

{{#invoke:JSON|mer|(JSON 코드1)|(JSON 코드2)|...}}

만약 중복된 항목이 있으면 2번 코드의 값으로 설정됩니다.

이를 응용하여 내용 수정에도 사용하실 수 있습니다. 만약 var1의 값을 6로 바꾸고 var2의 값을 true로 바꾸려는 경우 다음과 같이 입력해 주세요. 다만 new는 값을 제거하는 데에는 이용하실 수 없으며 JSON 코드를 직접 입력하셔야 합니다.

{{#invoke:JSON|mer|(JSON 코드)|{{#invoke:JSON|new|var1=6|var2=true}}}}

변수 제거

여러개의 변수를 일괄적으로 제거합니다.

{{#invoke:JSON|del|(JSON 코드)|(변수1)|(변수2)|...}}

작업 조합

만약 여러 작업을 동시에 하고 싶다면 cmd명령을 사용해 CGI2 방식으로 명령어를 입력하거나, 모듈:JSON/cmd를 사용하실 수 있습니다. 모듈:JSON/cmd는 JSON 코드 부분을 생략합니다.

{{#invoke:JSON|cmd
  |{{#invoke:JSON|new|var=false}}
  |{{#invoke:JSON/cmd|mer|
   {{#invoke:JSON|new
   |var1=6
   |var2={{#invoke:JSON|new|ㅁㄴㅇㄹ}}
   }}
  }}
  {{#invoke:JSON/cmd|del|var}}
  {{#invoke:JSON/cmd|get|var2}}
 }}

도보시오


--[[
	ko:
	JSON 모듈
	JSON 코드에 있는 값의 내용을 반환하거나, 값을 수정한 JSON 코드를 다시 반환합니다.
	이 코드는 일단 CC BY-NC-SA로 배포되나, 추후 CC BY-SA로 변경될 수 있습니다.
	한국어 백괴게임의 Gustmd7410이 만들었습니다.
]]--
--[[
	en:
	JSON Module
	You can get and change JSON code's value with this.
	This code is distributed with CC BY-NC-SA license, but it could be changed into CC BY-SA license later.
	Made by Gustmd7410 in Korean Ungame.
]]--
local a = {}
local b = setmetatable({
	rtyp = a.typ,
	typ = false
}, {
	__index = a
})
local p = setmetatable({}, {
	__index = function(t, key)
		return b[key] and function(frame)
			local args = getRawArgs(frame.args)
			local data = mw.text.jsonDecode(table.remove(args, 1))
			local value = b[key](data, args)
			
			if type(value) == "table"
				then return mw.text.jsonEncode(value)
				else return value
			end
		end or nil
	end
})
function getRawArgs(args)
	local raw = {}
	
	for key, value in pairs(args) do
		raw[key] = value
	end
	
	return raw
end

function settype(value)
	if value:find('^("+)(.*)%1$') and pcall(mw.text.jsonDecode, value:gsub('^("+)(.*)%1$', "%2")) then
		return value:gsub('^"(("+)(.*)%2)"$', "%1")
	elseif pcall(mw.text.jsonDecode, value) then return mw.text.jsonDecode(value)
	elseif value == "" then return nil
	else return value
	end
end

function p.typ(frame)
	local key = frame.args[2]
	key = tonumber(key) or key
	local value = mw.text.jsonDecode(frame.args[1])[key]
	
	if value == null then return "null" end
	
	return type(value)
end

function a.typ(data)
	return type(data)
end

function a.get(data, args)
	for depth, key in pairs(args) do
		key = tonumber(key) or key
		data = data[key]
	end
	
	return data
end

function a.set(data, args)
	local key = args[1]
	local value = mw.text.trim(args[2])
	key = tonumber(key) or key
	
	data[key] = settype(value)
	
	return data
end

function p.new(frame)
	local data = getRawArgs(frame.args)
	
	for key, value in pairs(data) do
		data[key] = settype(mw.text.trim(value))
	end
	
	return mw.text.jsonEncode(data)
end

function a.mer(base, args)
	for seq in pairs(args) do
		local data = mw.text.jsonDecode(args[seq])
		
		for key in pairs(data) do base[key] = data[key] end
	end
	
	return base
end

function a.del(data, args)
	for seq, key in pairs(args) do
		data[tonumber(key) or key] = nil
	end
	
	return data
end

function a.len(data)
	return #data
end

function a.con(data, args)
	return table.concat(data, args[2] or ',', tonumber(args[3]) or 1, tonumber(args[4]) or #data)
end

function a.ins(data, args)
	local index = tonumber(args[3]) or #data + 1
	
	if index < 0 then
		index = #data + index
	end
	
	table.insert(data, index, args[2])
	return data
end

function a.rem(data, args)
	for seq, key in pairs(args) do
		key = tonumber(key)
		
		if key < 0 then
			key = #data + key
		end
		
		table.remove(data, key)
	end
	
	return data
end

function a.srt(data, args)
	table.sort(data)
	return data
end

function a.srt_custom(data, args)
	table.sort(data, args[1])
	return data
end

function p.chk(frame)
	if pcall(mw.text.jsonDecode, frame.args[1])
		then return frame.args[2]
		else return frame.args[3]
	end
end

function p.str(frame)
	return mw.text.jsonDecode('"' .. frame.args[1] .. '"')
end

function p.pty(frame)
	local data = mw.text.jsonDecode(frame.args[1])
	return mw.text.jsonEncode(data, mw.text.JSON_PRETTY)
end

function p.cmd(frame)
	local data = mw.text.jsonDecode(frame.args[1])
	local commands = mw.text.jsonDecode('[' .. frame.args[2]:sub(1, -2) .. ']')
	local pretty = false
	
	for index, command in pairs(commands) do
		for action, args in pairs(command) do
			if action == 'pty' then
				pretty = true
			else
				data = a[action](data, args)
			end
			break
		end
	end
	
	if type(data) == "table" then
		return pretty and mw.text.jsonEncode(data, mw.text.JSON_PRETTY) or mw.text.jsonEncode(data)
	else
		return data
	end
end

function a.has(data, args)
	local valt = {}
	local result = nil
	
	for key, value in pairs(data) do
		valt[value] = true
	end
	
	for index, value in pairs(args) do
		if result == nil then result = true end
		if valt[value] ~= true then result = false end
	end
	
	return result
end

a['for'] = function(data, args)
	local text = ''
	local keyv = args.key or 'key'
	local valv = args.value or 'value'
	local func = require('모듈:TemplateFunction').new(args[1])
	
	for key, value in pairs(data) do
		if type(value) == "table" then
			value = mw.text.jsonEncode(value)
		end
		
		text = text .. func{
			[keyv] = key,
			[valv] = value
		}
	end
	
	return text
end

function a.map(data, args)
	local keyv = args.key or 'key'
	local valv = args.value or 'value'
	local func = require('모듈:TemplateFunction').new(args[1])
	
	for key, value in pairs(data) do
		if type(value) == "table" then
			value = mw.text.jsonEncode(value)
		end
		
		data[key] = settype(func{
			[keyv] = key,
			[valv] = value
		})
	end
	
	return data
end

function a.red(data, args)
	local val = ''
	local keyv = args.key or 'key'
	local valv = args.value or 'value'
	local prev = args.previous or 'previous'
	local func = require('모듈:TemplateFunction').new(args[1])
	
	for key, value in pairs(data) do
		if type(value) == "table" then
			value = mw.text.jsonEncode(value)
		end
		
		val = func{
			[keyv] = key,
			[valv] = value,
			[prev] = val
		}
	end
	
	return val
end

function p.spl(frame)
	local text = frame.args[1]
	local sep = frame.args[2]
	
	return mw.text.jsonEncode(mw.text.split(text, sep))
end

return p