SOLVED Problem with tables and dictionaries in datastore

Hello! I’m trying to make a datastore, all script is done, but it doesn’t save any data or it can’t load it.

Variables:

local DataStoreService = game:GetService("DataStoreService")
local DataStore = DataStoreService:GetDataStore("TimeStats")
local RunService = game:GetService("RunService")
local HttpService = game:GetService("HttpService")

Saving: (resources, backpackitems, etc are tables, except money, it is a number)

	table.insert(PlrData, money)
	table.insert(PlrData, Resources)
	table.insert(PlrData, BackPackItems)
	table.insert(PlrData,BackpackAmounts)

	DataStore:SetAsync("Items_"..tostring(Player.UserId), HttpService:JSONEncode(PlrData))
	print("saved")

Loading: (all the tables inside Data return nil values inside)

	local DataString = DataStore:GetAsync("Items_"..tostring(Player.UserId))
	local Data = HttpService:JSONDecode(DataString)
1 Like

There is no need for json encoding and decoding, roblox DataStoreService does it for you, that might be the issue

1 Like

It was already in the original script I took it from (I just used the script because I didn’t know what were the commands like SetAsync or GetAsync and I also didn’t know the variables for Datastore service. how can I remove the json encode, do I just take it off with the “,” before it?

1 Like

Here’s the code without the encoding

--Vars
local DataStoreService = game:GetService("DataStoreService")
local DataStore = DataStoreService:GetDataStore("TimeStats")
local RunService = game:GetService("RunService")
local HttpService = game:GetService("HttpService")

--Saving
table.insert(PlrData, money)
table.insert(PlrData, Resources)
table.insert(PlrData, BackPackItems)
table.insert(PlrData,BackpackAmounts)

DataStore:SetAsync("Items_"..tostring(Player.UserId), PlrData)
print("saved")

--Loading
local Data = DataStore:GetAsync("Items_"..tostring(Player.UserId))
1 Like

JSON encoding is a bad practice but it’s probably not causing this issue.

Are you testing in Studio or in the Player? Have you made sure to enable DataStore access in Studio?

Are there any errors being printed in the console? That could help us narrow down the issue.

1 Like

I tested and Nickname’s method didn’t work, probably because of the rest of the code. And I’m testing in roblox server (i published game) and API service is enabled, and no, no errors

1 Like

Here is the full script, what it prints is “new detected” which means the data received was nil

local DataStoreService = game:GetService("DataStoreService")
local DataStore = DataStoreService:GetDataStore("TimeStats")
local RunService = game:GetService("RunService")
local HttpService = game:GetService("HttpService")


function PosInArray (dictionary, PositionInDictionary)
	local Keys = {};

	for Key, Value in pairs(dictionary) do 
		table.insert(Keys, Key);
	end

	return dictionary[Keys[PositionInDictionary]];
end

function printTable(t)
	local str = ""
	for i, v in ipairs(t) do
		str = str .. string.format("\t[%d] = %f,\n", i, v)
	end
	print(string.format("local tab = {\n%s}", str))
end

game.Players.PlayerAdded:Connect(function(Player)
	local Success = false
	local BackPack = Player.Backpack

	local Data = DataStore:GetAsync("Items_"..tostring(Player.UserId))
	local leaderstats = Instance.new("IntValue")
	leaderstats.Name = "leaderstats"
	local money = Instance.new("IntValue",leaderstats)
	money.Name = "₡"
	money.Value = 0
	leaderstats.Parent = Player
	local role = Instance.new("StringValue",leaderstats)
	role.Name = "Role"
	role.Value = "None"
	leaderstats.Parent = Player
	if Data ~= tostring(nil) and not RunService:IsStudio() then
		if Data[1] ~= nil and Data[2] ~= nil and Data[3] ~= nil and Data[4] ~= nil then
			wait(1)
			money.Value = Data[1]
			local d = true
			local storage = game.ServerStorage
			local resources = Data[2]
			local backpack = Data[3]
			local amounts = Data[4]
			if resources[1] ~= nil then
				print(Data[1])
				printTable(Data[2])
				printTable(Data[3])
				printTable(Data[4])
				local resourceslist = {"Stone","Wood","Coal","Iron","Diamond","Obsidian","Leaves","Sand","Glass","Carrot","Tomato","Potato","Corn"}

				for i,v in pairs(resourceslist) do
					game.ServerStorage.PlayerData:FindFirstChild(Player.Name):FindFirstChild(v).Value = resources[v]
					if resources[i]  > 0 then
						d = false
					end
				end

				for count,z in pairs(backpack) do
					local obj = workspace
					for i,v in pairs(storage.Grabbables.Boxes:GetChildren()) do
						if v.Name == z then
							obj = v
						end
					end
					for i,v in pairs(storage.Grabbables.Drops:GetChildren()) do
						if v.Name == z then
							obj = v
						end
					end
					for i,v in pairs(storage.Grabbables.Tools:GetChildren()) do
						if v.Name == z then
							obj = v
						end
					end
					if obj ~= workspace then
						obj:Clone()
						for i,v in pairs(obj:GetDescendants()) do
							if v.Name == "Owner" then
								v.Value = Player.Name
							elseif v.Name == "Amount" then
								v.Value = amounts[count]
							elseif v.Name == "BillboardGui" then
								local parentname = v.Parent.Name
								if v.Parent.Name == "Handle" then
									parentname = v.Parent.Parent.Name
								end
								v.DROP.Text = amounts[count].."x "..parentname
							end
						end
					else
						print("lmao object is workspace, name is "..tostring(z))
					end
				end



				if #backpack == 0 and d == true then
					print("new detected")
					local cloned1 = storage.Axe:Clone()
					local cloned2 = storage.Pickaxe:Clone()
					cloned1.Parent = Player.Backpack
					cloned2.Parent = Player.Backpack
				else
					print("Loaded")
				end
			else
				print("new detected")
				local cloned1 = storage.Axe:Clone()
				local cloned2 = storage.Pickaxe:Clone()
				cloned1.Parent = Player.Backpack
				cloned2.Parent = Player.Backpack
			end
		end
	else
		local storage = game.ServerStorage
		print("new detected")
		repeat wait() until Player.Character
		wait(0.5)
		local cloned1 = storage.Axe:Clone()
		local cloned2 = storage.Pickaxe:Clone()
		cloned1.Parent = Player.Backpack
		cloned2.Parent = Player.Backpack
	end
end)

function save(Player)

	local PlrData = {}


	local Resources = {}
	local data = game.ServerStorage.PlayerData:FindFirstChild(Player.Name)
	--stone,wood,coal,iron,diamond,obsidian,leaves,sand,glass,carrot,tomato,potato,corn
	Resources["Stone"] = data.Stone.Value
	Resources["Wood"] = data.Wood.Value
	Resources["Coal"] = data.Coal.Value
	Resources["Iron"] = data.Iron.Value
	Resources["Diamond"] = data.Diamond.Value
	Resources["Obsidian"] = data.Obsidian.Value
	Resources["Leaves"] = data.Leaves.Value
	Resources["Sand"] = data.Sand.Value
	Resources["Glass"] = data.Glass.Value
	Resources["Carrot"] = data.Carrot.Value
	Resources["Tomato"] = data.Tomato.Value
	Resources["Potato"] = data.Potato.Value
	Resources["Corn"] = data.Corn.Value


	local BackPack = Player.Backpack
	local BackPackItems = {}
	local BackpackAmounts = {}
	for i,v in ipairs(BackPack:GetChildren()) do
		local amnt = 1
		for i,v in pairs(v:GetDescendants()) do
			if v.Name == "Amount" then
				amnt = v.Value
			end
		end
		table.insert(BackPackItems,v.Name)
		table.insert(BackpackAmounts,amnt)
	end


	local money = Player.leaderstats["₡"].Value

	table.insert(PlrData, money)
	table.insert(PlrData, Resources)
	table.insert(PlrData, BackPackItems)
	table.insert(PlrData,BackpackAmounts)

	DataStore:SetAsync("Items_"..tostring(Player.UserId), PlrData)
	print("saved")
end

game.Players.PlayerRemoving:Connect(function(Player)
	if not RunService:IsStudio() then
		save(Player)
	end
end)

local Players = game.Players
game:BindToClose(function()
	if not RunService:IsStudio() and #Players:GetPlayers() > 1 then
		for _, player in ipairs(Players:GetPlayers()) do
			coroutine.wrap(save)(player)
		end
	end
end)

also you should ignore the first 2 functions because they are for printing stuff in published game or getting position in dictionaries

Can you try using pcalls and see if an error is printed?
You can implement pcalls like this:

function getDataAsync(store: DataStore, key: string): any
	local success, data = pcall(function()
		return store:GetAsync(key)
	end)

	if success then
		print(data)
	else
		print("Error getting data")
	end

	return success, data
end


function saveDataAsync(store: DataStore, key: string, value: any): any
	local success, errorMessage = pcall(function()
		store:SetAsync(key, value)
	end)

	if not success then
		print(errorMessage)
	end

	return success, errorMessage
end

No errors also devforum says post must be thirty-characters so yeah making it long

I’ll try printing every value to see if it returns nil or if it returns something but the problem is my code
EDIT: nvm it already does that, my me from the past isn’t that dumb, yes it’s returning nil
EDIT2: this code checks if it is nil before printing, so yeah it’s not printing meaning it’s nil

			if resources[1] ~= nil then
				print(Data[1])
				printTable(Data[2])
				printTable(Data[3])
				printTable(Data[4])

I tried printing the tables before checking if it’s nil and in console every table has nothing inside, so basically what the GetAsync returned was: Money = 0, Resources = {}, Backpack = {}, BackpackAmounts = {}

After a long time of searching lots of datastore posts on Devforum, I finally came to the solution that: In datastores, you can’t use dictionaries and non-dictionaries in the same table, they must be a dictionary or a table, not mixed. In my case I was using mixed. So I fixed it for all to not be dictionaries and it worked.

Basically, for who ended up in this post while searching for datastore help:
-You do not need JSONEncode or decode for roblox datastore, it does it automatically.
-Make sure that you are only using a dictionary or table for each datastore call, and not mixed.
-And yeah, you can put tables inside tables in datastore, but even if a table is inside a table that table still has to be the same type as the top one (dictionary or table)

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.