[Open Sourced] Data Deserializer And Instance Serializer

Alright so I have seen quite a few people requesting data deserializers and instance serializers so I am here to show you a simple derserializer&serializer I made. I am providing steps on how it works and script. The deserializer&serializer only saves parts, and only 5 properties of them, their size, position, class name, name and if the part is anchored or not. It automatically “saves the workspace” when the game gets shut down. I do realize that if there were to be 2 servers running for example one of the servers would lose data I am doing this just to show how you would go about making a derserializer&serializer. This was mainly made to give an idea on how a deserializer and serializer works.
Here is how it works:

Game runs.
Game gets the data of the game from the datastore, a JSON encoded dictionary.
Data gets JSON decoded into a dictionary.
Data (the dictionary) then gets deserialized by my own deserializer.
For every new child added or removed the dictionary gets the elements of the workspace and their properties and adds them in the dictionary, currently it only gets 5 properties, does not save the baseplate, camera, the terrain or the players’ character. Basically here the serialization process occurs.
Game shuts down.
The dictionary gets JSON encoded.
The dictionary gets saved in the datastore.

So yeah. Here is the script for that:

--//Data Deserializer And Instance Serializer
--//Scripted by vamik64
local DSS = game:GetService("DataStoreService")
local HttpService = game:GetService("HttpService")
local serverDSS = DSS:GetDataStore("serverDSS_1")
local Players = game:GetService("Players")

local Workspace = {}

local function updateDictionary()
	Workspace = {}
	for i, v in pairs(workspace:GetChildren()) do
		if v.Name ~= "Camera" and v.Name ~= "Terrain" and v.Name ~= "Baseplate" and v:IsA("Part") then
			for _, plr in pairs (game:GetService("Players"):GetPlayers()) do
				if plr.Name == v.Name and v:IsA("Model") and v:FindFirstChild("Humanoid") ~= nil then
					return
				end
			end
			local a = {}
			a.Position = {v.Position.X, v.Position.Y, v.Position.Z}
			a.Size = {v.Size.X, v.Size.Y, v.Size.Z}
			a.Name = {v.Name}
			a.Anchored = {v.Anchored}
			a.ClassName = {v.ClassName}
			table.insert(Workspace, a)
			
		end	
end
		
	dataTOsave = HttpService:JSONEncode(Workspace)
end

function DecodeDictionary(dic)
	local inst = nil
	for i, v in pairs(dic) do
		for a, b in pairs(v) do
			if a == "ClassName" then
                if  b[1] ~= "Part" then
                return
                end
				inst = Instance.new(b[1])
				inst.Parent = workspace
				print("Decoded "..inst.Name)
			end
		end
		for a, b in pairs(v) do
			if a == "Size" then
				inst.Size = Vector3.new(b[1], b[2], b[3])
			elseif a == "Position" then
				inst.Position = Vector3.new(b[1],b[2],b[3])
			elseif a == "Name" then
				inst.Name = b[1]
			elseif a == "Anchored" then
				inst.Anchored = b[1]
			end		
		end
			end
end
			
local JSONdata = serverDSS:GetAsync("server_key")
if JSONdata ~= nil and JSONdata ~= "[]" then
	local data = HttpService:JSONDecode(JSONdata)
	DecodeDictionary(data)
end

			
workspace.ChildAdded:Connect(function()
	updateDictionary()
end)

workspace.ChildRemoved:Connect(function()
	updateDictionary()
end)

game:BindToClose(function()
     print("JSON encoded dictionary:\r "..dataTOsave)
	serverDSS:SetAsync("server_key", dataTOsave)
end)

The lines of code I have written can easily be reduced. I might not be using the most efficient method but here is how I made mine! Also this is my first contribution to the DevForum’s community :slight_smile:. I am open to/accept criticism so if you want to criticize me, give me ideas, give me your opinion I would love to hear it!

6 Likes

The main problem I see with your Instance Serializer is the fact that you don’t store parents, meaning that you wouldn’t be able to have parts parented to parts, but only parts exclusively parented to the workspace.

Anyone who’s making a building game of sort that requires saving, I’d definitely suggest looking into making a better serializer, as your take on it isn’t accounting for many things.

4 Likes

Yes you are right. Making an instance serializer which parents a part to another one might be a bit harder but it still can be achieved with some effort. I am just giving an idea of deserializer&serializer. Thanks for letting me know that :slightly_smiling_face:

Explain what this does to me. I’m a bit of an idiot.

Serialization is the process of converting an object into a stream of bytes. Deserialization is the opposite process of creating an object from a stream of bytes.

g o o g l e ®

2 Likes

Maybe make a little bit more reliable DataStore saving. The recent issues with lost data have people a little bit on edge :yum:

Also to go along with Legoracer’s comment, you are currently getting workspace’s Children instead of Descendants. Make sure you change that if you end up serializing the parents.

I am using datastore for the sake of this tutorial I use personally use DataStore2. I thought it would be better to not mess topics. It is obvious that anyone can use whatever they find useful for datastoring. And yes I should’ve used :GetDescendants but since I am not parenting the product of the deserialization process I thought I should use :GetChildren as I did not see a point for using :GetDescendants. If anyone else is making the same thing I am they should definitely store their data in a better way and use :GetDescendants. Thanks for your suggestions/tips :slightly_smiling_face: !

2 Likes

Alright so my script has some minor issues which can easily be fixed, for example the data won’t save if you do changes to parts due to not detecting these changes. I am also using .ChildAdded and not DescendantAdded so yeah.
I am glad to announce that I am working on a new deserializer and serializier which will be able to serialize and deserialize almost everything!

6 Likes

Thanks I needed this and can’t wait for your next one