Turn a dictionary into string

im looking to turn this table / dictionary

local EntryTable = {
	["Entry1"] = "CoolText",
	["Entry2"] = "NotSoCoolText"
}

into a string

ive looked at other topics and they just show something with string.format but never really explain what it does

1 Like

table.concat

Oh wait, it’s a dictionary. You’ll need to do something else a little more complex:

local str = ""
for key, value in pairs(EntryTable) do
str..=`{key}: {value}\n`
end
print(str)

What this does is creates a blank string and appends the key to the value in the dictionary, and then the value. Then, the newline character is added so the next item is displayed on another line.

2 Likes

What structure should it be? Does it need to be nicely formatted?

If not you can use HttpService:JSONEncode() like so:

local HttpService = game:GetService("HttpService")

local text = HttpService:JSONEncode(EntryTable)

Which will set text to {"Entry2":"NotSoCoolText","Entry1":"CoolText"}

1 Like

Cool, how exactly does it turn the value and key into string formation? is it something with the {} and the ‘’?

And also how should i go about turning it back into dictonary formation?

id prefer if it was, id like to somewhat easily be able to read & modify it on the go

That is just the string interpretation. You could also do str..=key..": "..value.."\n".

You can use string.split:

local backToDictionary = {}
local newlineSeparators = str:split("\n")
for _, str in newlineSeparators do
--let's say 'str' = "Entry1: CoolText"
local keyToValue = str:split(": ")
if not keyToValue or not keyToValue[1] or not keyToValue[2] then continue end
--keyToValue[1] = "Entry1"
--keyToValue[2] = "CoolText"
backToDictionary[keyToValue[1]] = keyToValue[2]
--we are basically doing backToDictionary["Entry1"] = "CoolText"
end

Written on DevForum, untested. This code might error.

What this does is some string logic to separate out the keys and values to put them back in the dictionary by assigning the value to the index before the ": ".

this did work, it and seems alot simplier than whatever those other scripts i looked at were doing.

just one more thing though?
if i had a entry somewhat like this

local EntryTable = {
	["Entry1"] = "CoolText",
	["Entry2"] = "NotSoCoolText",
	["Entry3"] = {["FirstEntry"] = "BoringEntry", ["SecondEntry"] = "SuperCoolText"}
}

im just guessing but would it be something like this to turn it into a string?

for Key, Value in pairs(EntryTable) do
	if typeof(Value) ~= "table" then
		String..=`{Key}:{Value} | `
	elseif typeof(Value) == "table" then
		String..=`{Key}:(`
		for Key2, Value2 in pairs(Value) do
			String..=`{Key2}:{Value2} | `
		end
		String..=") | "
	end
end

if this is how then ill just need a bit of time to figure out how to revert it back to dictionary format

(edit)
used typeof instead of value == table

(edit2)
did some of my own research and got this code now

local EntryTable = {
	["Entry1"] = "CoolText",
	["Entry2"] = "NotS oCoolText",
	["Entry3"] = {["FirstEntry"] = "BoringEntry", ["SecondEntry"] = "SuperCoolText"}
}

local String = ""
for Key, Value in pairs(EntryTable) do
	if typeof(Value) ~= "table" then
		String..=`{Key}:{Value} | `
	elseif typeof(Value) == "table" then
		String..=`{Key}:(`
		for Key2, Value2 in pairs(Value) do
			String..=`{Key2}:{Value2} | `
		end
		String..=") | "
	end
end

print(String)

local Values = {}

local Pattern = "(%w+:%b())"
local Pattern2 = "(%w+:(%w+)[%w%s]+)"

for Key, Value in string.gmatch(String, Pattern) do
	if Key then
		table.insert(Values, Key)
		local split = string.split(String, Key)
		String = ""
		for i, v in pairs(split) do
			String..=v
		end
	end
end

for Key, Value in string.gmatch(String, Pattern2) do
	if Key then
		table.insert(Values, Key)
	end
end

i know get to the result of this


(if i print the Value table)
i just need to figure out how to split the first entry without spliting it at the other points aswell.

It would be better to do this with a recursive function to convert to and from a dictionary, but it’s quite easy to split this one.

First, you need to search for Entry1, the first entry:

local entryFind = String:find("Entry1") --this is a number

and then, you can simply perform the split:

local entry1OnlyData = String:sub(entryFind):split(":")[2] --> CoolText

Written on DevForum, untested. Code may error.

Keep in mind you need to subtract the find so that the string starts with “Entry1”.

For example, if I had “Hello World” and I subtracted the first 6 letters, I only get “World”. That is what this code is doing.

for this to work wouldn’t you need the name of the key first?, what if the key’s names were randomized or something (not sure why they would be (Probably since pairs can randomize the table to some extent)) wouldn’t i still need to figure out what the keyname before the : is?

Yes, you would. Though, I’m not sure what other possible method you would do to index these and not know the name.

mean there probably is some sort of method to get all the letters behind the colon but then you would have to do even more to account for the spaces and stuff

and for some of the stuff I’m doing
(["Entry3"] = {["FirstEntry"] = "BoringEntry", ["SecondEntry"] = "SuperCoolText"})
id have to find a way so it doesn’t grab the values within the parenthesis

on another note going back to this

i could use this in a way where i get a pattern like "(%w+:)" and just get the resulting text from this (if im using the already made Value table from before) and just use the method you said above

Here is a code snippet with a compiler and decompiler:

local HttpService = game:GetService("HttpService")

local NEW_LINE_TRIGGERS = {
	",", "{"
}

local NEW_BREAK_TRIGGERS = {
	"}", "]"
}

local function CompileJSONTable(Table)
	local Result = HttpService:JSONEncode(Table)
	
	for _, Trigger in NEW_LINE_TRIGGERS do
		Result = Result:gsub(Trigger, Trigger .. "\n")
	end
	
	for _, Trigger in NEW_BREAK_TRIGGERS do
		Result = Result:gsub(Trigger, "\n" .. Trigger)
	end
	
	return Result
end

local function DecompileJSONTable(String)
	for _, Trigger in NEW_LINE_TRIGGERS do
		String = String:gsub(Trigger .. "\n", Trigger)
	end
	
	for _, Trigger in NEW_BREAK_TRIGGERS do
		String = String:gsub("\n" .. Trigger, Trigger)
	end

	return HttpService:JSONDecode(String)
end
1 Like

If you’re only adding newlines then you don’t need to remove them for HttpService:JSONDecode() to work.

Also you should make it add some indentation so it’s easier to read.
image
(also add [ to NEW_LINE_TRIGGERS?)

I tried, but Lua doesn’t like that with gsub.

seems more compact, although i dont really understand a single thing from this tbh
especially looking at the output here

looks real complex

atleast for me since i dont understand much about string manipulation and stuff

did this and got this

for Key, Value in string.gmatch(String, Pattern) do
	if Key then
		table.insert(Values, Key)
		local split = string.split(String, Key)
		String = ""
		for i, v in pairs(split) do
			String..=v
		end
	end
end

for Key, Value in string.gmatch(String, Pattern2) do
	if Key then
		table.insert(Values, Key)
	end
end

if #Values > 1 then
	for i, v in ipairs(Values) do
		local Key = string.match(v, ("[%w%s]+"))
		local SplitNumber = string.find(v, ":")
		local Split = string.sub(v, SplitNumber)
		if not string.find(Split, "(%b())") then
			local Value = string.split(Split, ":")[2]
			RemadeTable[Key] = Value
		end
	end
end

althought i got 2 issues with it right now
local Key = string.match(v, ("[%w%s]+")) does not get the full key if it has spaces in it for some reason
local Value = string.split(Split, ":")[2] the value has a space at the end of it dont know why :smiley: