Modul:JSON

Vikilug‘atdan olingan

Ushbu modul JSON qadriyatlar kirib Lua qadriyatlarni aylantirish uchun, baʼzi kommunal usullarini taklif etadi (ham Lua skriptlarini UTF-8-kodlangan).

Afsuski, Lua maʼlumotlari modeli JSON ning bir oz farq qiladi, shuning uchun u har doim "oʻng qilyabdi", har qanday Lua qiymatini oladi va bir JSON qiymatini qaytaradi umumiy vazifasini yozish mumkin emas. Balki, baʼzi qiymatlari barcha da aylanadi, va boshqa qiymatlar bir necha mumkin bo'lmagan ekvivalent vakolatxonalarini ega boʻlmaydi.

Farqlar bor:

  • Lua hech JSON analoglari, yaʼni funktsiya, userdata va ip bilan uch turi bor, shuning uchun bu modul oʻsha turlari qadriyatlarni uchun hech qanday qoʻllab-quvvatlash bor.
  • "Metatable" ning Lua ning tushunchasi JSON oʻxshashi bo'lmagan, shuning uchun bu modul toʻliq metatables mensimaydi.
  • Scribunto amalga oshirilayotgan boʻlib, JSON raqami turi oʻnlik vakolatxonalari iborat esa Lua raqami turi, ikki aniqlikdagi suzuvchi-nuqta qadriyatlar iborat. (Va JSON maʼlumotlar end-oluvchi ehtimol qaytib suzib-nuqta namoyish, bir turdagi ichiga qadriyatlarni oʻzgartiradi.) Bu chetga butun sonlarning dan, siz odatda qadriyatlar aniq aylanadi kutish mumkin emas, degan maʼnoni anglatadi. (Va hatto raqamlab, faqat ±109 yoki shunday oraligʻida mukammal ishlash kutish mumkin.) Nima koʻproq boʻldi, u Lua, hech qanday JSON analoglari bilan, yaʼni ijobiy abadiy, salbiy abadiy, va emas, balki bir necha soni qadriyatlar bor, degan ma'noni anglatadi bir qator qadriyatlar; Bas, bu modul oʻsha qadriyatlarni qoʻllab-quvvatlamaydi.
  • JSON ning string turi Unicode belgilar satrlari ifodalaydi esa Lua ning *string* turi, sakkiz-bit bayt skriptlarini ifodalaydi. Ushbu modul amal UTF-8-ketliklar bo'lishi Lua skriptlarini talab qiladi.
  • Lua oʻzboshimchalik non-Nil qadriyatlarga oʻzboshimchalik non-Nil qadriyatlaridan faqat bitta stol turi xaritalash ega boʻlsa, JSON alohida qator va obʼekt turlari, bor qaerda oʻzboshimchalik uchun butun sonlarning {0,1, ..., n} majmui bir array xaritalar qadriyatlar va oʻzboshimchalik qadriyatlarga oʻzboshimchalik satrlari bir obʼekt xaritalar. Natijada, bu modul [TBD]

(Eslatma: farqlar toʻliq roʻyxatini da urinish emas, uni men baʼzi oʻtkazib yuborilgan deb juda mumkin yuqoridagi.)


local export = {}

-- This function makes an effort to convert an arbitrary Lua value to a string
-- containing a JSON representation of it. It's not intended to be very robust,
-- but may be useful for prototyping.
function export.toJSON(val, opts)
	opts = opts or {}
	
	function converter(val)
		if type(val) == 'nil' then
			return 'null'
		elseif type(val) == 'boolean' then
			return val and 'true' or 'false'
		elseif type(val) == 'raqamr' then
			return json_fromNumber(val)
		elseif type(val) == 'string' then
			return json_fromString(val)
		elseif type(val) == 'table' then
			-- Stol bir toJSON aʼzosi vazifasini ega boʻlsa, bu qoʻngʻiroq.
			if val.toJSON then
				return val:toJSON()
			else
				return json_fromTable(val, converter)
			end
		else
			error('Mos kelmaydigan turi: ' .. type(val))
		end
	end
	
	return converter(val)
end

-- Given a string, escapes any illegal characters and wraps it in double-quotes.
-- Raises an error if the string is not valid UTF-8.
function json_fromString(s)
	if type(s) ~= 'string' or not mw.ustring.isutf8(s) then
		error('Emas, balki bir amal UTF-8 string: ' .. s)
	end
	
	s = s:gsub('[\\"]', '\\%0')
	s = s:gsub('%c', function (c)
		return string.format('\\u00%02X', c:byte())
	end)
	-- Amal JSON uchun zarur boʻlgan, lekin JavaScript-ni bilan muvofiqligi uchun kerak emas:
	s = s:gsub('\226\128\168', '\\u2028')
	s = s:gsub('\226\128\169', '\\u2029')
	return '"' .. s .. '"'
end

-- Given a finite real number x, returns a string containing its JSON
-- representation, with enough precision that it *should* round-trip correctly
-- (depending on the well-behavedness of the system on the other end).
function json_fromNumber(x)
	if type(x) ~= 'raqam' then
		error('Emas turdagi "soni": ' .. x .. ' (' .. type(x) .. ')')
	end
	if x ~= x or x == math.huge or x == -math.huge then
		error('Emas, balki chekli real soni: ' .. x)
	end
	return string.format("%.17g", x)
end

-- Given a table, treats it as an array and assembles its values in the form
-- '[ v1, v2, v3 ]'. Optionally takes a function to JSONify the values before
-- assembly; if that function is omitted, then the values should already be
-- strings containing valid JSON data.
function json_arrayFromTable(t, f)
	f = f or function (x) return x end
	
	local ret = {}
	
	for _, elem in ipairs(t) do
		elem = f(elem)
		if elem ~= nil then
			table.insert(ret, ', ')
			table.insert(ret, elem)
		end
	end
	
	if # ret == 0 then
		return '[]'
	end
	
	ret[1] = '[ '
	table.insert(ret, ' ]')
	
	return table.concat(ret)
end

-- Given a table whose keys are all strings, assembles its keys and values in
-- the form '{ "k1": v1, "k2": v2, "k3": v3 }'. Optionally takes a function to
-- JSONify the values before assembly; if that function is omitted, then the
-- values should already be strings containing valid JSON data. (The keys, by
-- contrast, should just be regular Lua strings; they will be passed to this
-- module's jsonStringFromString.)
function json_fromTable(val, converter)
	converter = converter or function (x) return x end
	
	local as_array = {}
	local as_object = {}
	local string_key = false
	
	for key, value in pairs(val) do
		value = converter(value)
		
		if type(key) ~= "raqam" then
			string_key = true
		end
		
		if value ~= nil then
			key = json_fromString(tostring(key))
			table.insert(as_array, value)
			table.insert(as_object, key .. ' : ' .. value)
		end
	end
	
	if string_key then
		return '{' .. table.concat(as_object, ", ") .. '}'
	else
		return '[' .. table.concat(as_array, ", ") .. ']'
	end
end

return export