Stringifier: turn basic Roblox data types into string tables - and SAVE them! (CFrame, Color3, Vector3 and more)

Welcome!

Introduction:

Working with Roblox data stores can be challenging, especially when trying to save data types such as CFrames, UDim2s and other. Roblox DataStores only accept strings and string-tables. Therefore, a good module is needed to turn basic Roblox data types into a format that can be saved - and retrieved.

Module link (version 1.0.0):
Stringify.rbxl (77.2 KB)

Instructions:

  1. Download the file above.
  2. Inside it, you’ll find a ModuleScript located in ServerScriptService.
  3. Copy the ModuleScript into the ServerScriptService of your own game.
  4. Require it in your scripts using:
local Stringify = require(game.ServerScriptService.Stringify)

Function toStringTable(object)

Converts a Roblox object/value into a table of strings that can be safely stored in a DataStore.

Parameters:
object → The Roblox data type to serialize (CFrame, UDim2, Vector3, Color3, etc.).

Returns:
A table of strings representing the object.

Example:

local vector = Vector3.new(1, 2, 3)
local serialized = Stringify.toStringTable(vector)
-- serialized can now be saved into a DataStore

Function toObject(stringTable, typeName)

Reconstructs the original Roblox object from a table of strings.

Parameters:
stringTable → The table of strings previously returned by toStringTable.
typeName → A string representing the object type (“Vector3”, “CFrame”, “UDim2”, etc.).

Returns:
The reconstructed Roblox object.

Example:

local originalVector = Stringify.toObject(serialized, "Vector3")

Examples:

We will attempt to get some test data,

  1. stringify it
  2. save it in a Roblox data store
  3. retrieve it
  4. return them back into the original data format

This will demonstrate that the module works for saving various data types and retrieving them.

-- obtaining the data store
local DataStoreService = game:GetService("DataStoreService")
local TestDS = DataStoreService:GetDataStore("Test")

-- Loading the module
local Stringifier = require(script.Parent:WaitForChild("Stringifier"))

-- example data
local ExampleNumber = 122
local ExampleString = "a string"
local ExampleCFrame = workspace.Baseplate.CFrame
local ExampleBoolean = true
local ExampleUDim = UDim.new(0.5, 10)
local ExampleUDim2 = UDim2.new(0.25, 20, 0.75, 40)
local ExampleBrickColor = BrickColor.new("Bright red")
local ExampleColor3 = Color3.new(1, 0.5, 0.25)
local ExampleVector2 = Vector2.new(10, 20)
local ExampleVector3 = Vector3.new(1, 2, 3)
local ExampleNumberSequence = NumberSequence.new{
	NumberSequenceKeypoint.new(0, 0),
	NumberSequenceKeypoint.new(0.5, 1),
	NumberSequenceKeypoint.new(1, 0.2)
}
local ExampleColorSequence = ColorSequence.new{
	ColorSequenceKeypoint.new(0, Color3.new(1,0,0)),
	ColorSequenceKeypoint.new(0.5, Color3.new(0,1,0)),
	ColorSequenceKeypoint.new(1, Color3.new(0,0,1))
}
local ExampleNumberRange = NumberRange.new(10, 50)

-- serializing/stringifying the data
local FormattedData = {
	Stringifier.toStringTable(ExampleNumber),
	Stringifier.toStringTable(ExampleString),
	Stringifier.toStringTable(ExampleCFrame),
	Stringifier.toStringTable(ExampleBoolean),
	Stringifier.toStringTable(ExampleUDim),
	Stringifier.toStringTable(ExampleUDim2),
	Stringifier.toStringTable(ExampleBrickColor),
	Stringifier.toStringTable(ExampleColor3),
	Stringifier.toStringTable(ExampleVector2),
	Stringifier.toStringTable(ExampleVector3),
	Stringifier.toStringTable(ExampleNumberSequence),
	Stringifier.toStringTable(ExampleColorSequence),
	Stringifier.toStringTable(ExampleNumberRange),
}

-- saving the test data
local success, err = pcall(function()
	TestDS:UpdateAsync("Test", function(prev)
		return FormattedData
	end)
end)
if not success then
	warn(err)
else
	print("Data saved successfully!")
end

-- retrieving the test data
local loadedData = {}
local success, err = pcall(function()
	loadedData = TestDS:GetAsync("Test")
end)
if not success then
	warn(err)
else
	print("Data loaded successfully!")
end

-- deserializing the data back into usable objects
local DeserializedData = {}
for i, item in ipairs(loadedData) do
	table.insert(DeserializedData, Stringifier.toObject(item))
end

-- printing the deserialized data for verification
for i, obj in ipairs(DeserializedData) do
	print(".")
	print("Returning a saved value after deserialization")
	print(i, obj, typeof(obj))
	print(".")
end

Information:

Version: 1.0.0
Supports: number, string, boolean, CFrame, UDim, UDim2, BrickColor, Color3, Vector2, Vector3, NumberSequence, ColorSequence, NumberRange
This will probably be expanded further

You don’t need to give me credits for using this module. Please just don’t replicate it here, or claim its ownership.

9 Likes

It would be cool if Stringifier.toObject(item) returned a tuple (type: string, object: any)

local unknownType = Stringifier.toStringTable(somewhereVariable)

local object_type, object_data = Stringifier.toObject(unknownType)

print(object_type) --> "NumberSequence"

of course there is always typeof(Stringifier.toObject(unknownType)), but I think it could be cool

1 Like

Thank you for the suggestion! The core idea of the module is to enable developers to just insert and retrieve data types from a data store, without additional parsing. That may confuse beginner level developers. But I like the idea!

1 Like