It might be a good idea to tell your use case. Also, what do you mean by “I want the code to be readable by well the script ig”? As @JohnyGamingAltAcc said, you can convert a json string back to a table with :JsonDecode. That’s what I would first assume “readable by the script” to mean.
If your goal is to compress the data and later convert it back to the original data then JsonEncode and JsonDecode are not the right approach since json strings are meant to be human readable, not memory efficient. The best way to compress the data depends on the situation.
If you mean that you want to be able to use the returned string in a script’s source code as a table constructor, then the function convertTableToLuauTableConstructor
in the code below could work for you. There are more datatypes that this could support but I didn’t want to include a huge number of datatypes when I don’t even know if this is what you are looking for. A lot of the code is red in this post because devforum code formatting isn’t compatible with Luau string interpolation.
Here's the code with the conversion function.
--!strict
local function getInstancePath(instance: Instance): string
if instance ~= game and not instance:IsDescendantOf(game) then
error("This Instance is not the DataModel or a descendant of the DataModel so it is not possible to get an instance hierarchy path for it.")
end
local fullName: string = ""
local current: Instance = instance
while current ~= game do
for _, siblingOrSelf: Instance in (current.Parent :: Instance):GetChildren() do
if siblingOrSelf == current then
continue
end
if siblingOrSelf.Name == current.Name then
error("Ambiguous path.")
end
end
local nameString: string = if string.match(current.Name, "%s") ~= nil then `[\"{current.Name}\"]` else `.{current.Name}`
fullName = nameString .. fullName
current = current.Parent :: Instance
end
fullName = "game" .. fullName
return fullName
end
local function convertToString(value: any): string
if typeof(value) == "string" then
return `\"{value}\"`
elseif typeof(value) == "number" then
return tostring(value)
elseif typeof(value) == "boolean" then
return tostring(value)
elseif typeof(value) == "Instance" then
return getInstancePath(value)
elseif typeof(value) == "Vector2" then
return `Vector2.new({value.X}, {value.Y})`
elseif typeof(value) == "Vector2int16" then
return `Vector2int16.new({value.X}, {value.Y})`
elseif typeof(value) == "Vector3" then
return `Vector3.new({value.X}, {value.Y}, {value.Z})`
elseif typeof(value) == "Vector3int16" then
return `Vector3int16.new({value.X}, {value.Y})`
elseif typeof(value) == "CFrame" then
local x: number, y: number, z: number, R00: number, R01: number, R02: number, R10: number, R11: number, R12: number, R20: number, R21: number, R22: number = value:GetComponents()
return `CFrame.new({x}, {y}, {z}, {R00}, {R01}, {R02}, {R10}, {R11}, {R12}, {R20}, {R21}, {R22})`
elseif typeof(value) == "UDim" then
return `UDim.new({value.Scale}, {value.Offset})`
elseif typeof(value) == "UDim2" then
return `UDim2.new({value.X.Scale}, {value.X.Offset}, {value.Y.Scale}, {value.Y.Offset})`
elseif typeof(value) == "Color3" then
return `Color3.new({value.R}, {value.G}, {value.B})`
elseif typeof(value) == "Enums" then
return "Enum"
elseif typeof(value) == "Enum" then
return `Enum.{tostring(value)}`
elseif typeof(value) == "EnumItem" then
return tostring(value)
else
error(`Unhandled datatype: {typeof(value)}`)
end
end
local function getKeyString(key: any): string
if typeof(key) == "string" then
return if string.match(key, "%s") == nil then key else `[{convertToString(key)}]`
end
return `[{convertToString(key)}]`
end
local function convertTableToLuauTableConstructorRecursive(tabl: {[any]: any}, multiline: boolean, depth: number): string
local indentation: string = "\t"
local minimumIndentation: string = string.rep(indentation, depth)
local separator: string = if multiline then `,\n{minimumIndentation .. indentation}` else ", "
local str: string = if multiline then (if depth == 0 then `\n\{\n{minimumIndentation .. indentation}` else `\{\n{minimumIndentation .. indentation}`) else "{"
local loopIsCurrentlyInArrayPart: boolean = true
local previousArrayIndex: number = 0
for key: any, value: any in tabl do
if loopIsCurrentlyInArrayPart and key ~= previousArrayIndex + 1 then
loopIsCurrentlyInArrayPart = false
else
previousArrayIndex = key :: number
end
local valueString: string = if typeof(value) == "table" then convertTableToLuauTableConstructorRecursive(value, multiline, depth + 1) else convertToString(value)
if loopIsCurrentlyInArrayPart then
str ..= valueString
else
local keyString: string = if typeof(key) == "table" then `[{convertTableToLuauTableConstructorRecursive(key, multiline, depth + 1)}]` else getKeyString(key, loopIsCurrentlyInArrayPart)
str ..= `{keyString} = {valueString}`
end
if next(tabl, key) ~= nil then
str ..= separator
end
end
str ..= if multiline then (if depth == 0 then `\n{minimumIndentation}\}\n` else `\n{minimumIndentation}\}`) else "}"
return str
end
local function convertTableToLuauTableConstructor<TKey, TValue>(dictionary: {[TKey]: TValue}, multiline: boolean): string
return convertTableToLuauTableConstructorRecursive(dictionary, multiline, 0)
end
Here's some code that I used for testing it.
local part: Part = Instance.new("Part")
local childPart: Part = Instance.new("Part")
childPart.Name = "Child Part"
local descendantPart: Part = Instance.new("Part")
descendantPart.Name = "DescendantPart"
descendantPart.Parent = childPart
childPart.Parent = part
part.Parent = workspace
local tabl: {[any]: any} = {
"number1",
"number2",
"number3",
hi = 1.5,
[3.25] = CFrame.new(9, 9, 9),
[descendantPart] = "bye",
[UDim2.new(1, 2, 3, 4)] = Vector3.new(3, 2, 1),
[UDim.new(1, 2)] = Vector2.new(2, 1),
[Vector2int16.new(1, 2)] = Vector3int16.new(2, 1),
nestedTable = {
something = Enum,
["something else"] = Enum.KeyCode,
[Enum.KeyCode.H] = Color3.new(.5, .5, .5),
[true] = false,
moreDeeplyNestedTable = {
somethingVeryDeep = "This is deep."
}
},
[{
hi = "hi"
}] = {
bye = "bye"
}
}
print(convertTableToLuauTableConstructor(tabl, true))