Saving not working with JSON

Saving plots:

function savePlot(player, playersPlot)
	local playerItems = {}

	for _, item in pairs(playersPlot.Purchases:GetChildren()) do
		print(item.Name)
		local itemData = {}
		local primaryPart = item.PrimaryPart
		local position = playersPlot.PrimaryPart.CFrame:inverse() * primaryPart.Position
		local direction = primaryPart.CFrame.lookVector
		
		itemData.ItemName = item.Name
		itemData.Position = {
			position.X, 
			position.Y, 
			position.Z, 
			direction.X, 
			direction.Y, 
			direction.Z
		}
		playerItems[#playerItems + 1] = itemData
	end
	
	local user = playerData[player.UserId]
	
	table.insert(user.Items, playerItems)
	print('saving total: ', #user.Items)
	user.Gold = 50
	print(user.Gold)
	dataManager:SaveData(player)
	print('Save done!')
end

Prints everything correctly, 50 cash, 1 item inside the user.Items in the data.

Loading plots

function loadPlot(player, playersPlot)
	print('Load started!')
	local user = playerData[player.UserId]
	if not user then return end
	print(#user.Items)
	print(user.Cash)
	for _, item in pairs(user.Items) do
		local targetModel = item.ItemName
		local information = item.Position
		local newItem = game.ReplicatedStorage.Items:FindFirstChild(targetModel):Clone()
		
		local position = playersPlot.PrimaryPart.CFrame*Vector3.new(
			information[1], 
			information[2], 
			information[3]
		)
		
		local lookVector = Vector3.new(
			information[4], 
			information[5], 
			information[6]
		)
		
		newItem:SetPrimaryPartCFrame(
			CFrame.new(
				position, 
				position + (lookVector*5)
			)
		)
		
		newItem.Parent = playersPlot.Purchases
		print('Loaded done')
	end
end

Prints 0 and 0 for the user.Cash and user.Items (and thus not running the for loop)

Saving function

function dataManager:SaveData(player)
	local saveJSON = httpService:JSONEncode(playerData[player.UserId])
	playerDataStore:SetAsync(player.UserId, saveJSON)
end

This is what gets the data when a player joins (just in case it’s important as well)

function dataManager:GetData(player)
	local loadJSON = playerDataStore:GetAsync(player.UserId)
	local setData = (loadJSON and httpService:JSONDecode(loadJSON)) or {}
	
	playerData[player.UserId] = updateObject(setData, data)
	    	
	dataReady = true
end

EDIT I found the problem:

function updateObject(old, new)
    local update = {}
    for i, v in next, new do
        update[i] = (type(v) == 'table' and old[i] and updateObject(old[i], v)) or old[i] or v
    end

    return update
end

local loadJSON = playerDataStore:GetAsync(player.UserId) or {}
	local setData = httpService:JSONDecode(loadJSON) or {}
		
	playerData[player.UserId] = setData--updateObject(setData, data)

If I go setData on playerData, it works. The commented out section is what I had before, and with that it breaks. Problem with removing this is if I add some more values to the data store, players who already have saved data won’t be able to get those new values, as they will load in an old data store.

Hi,

Just try with just:
local setData = httpService:JSONDecode(loadJSON)) or {};

You could also add a print, printing the loadJSON data still not parsed to see if it’s there.

Still not loading up saved data, still prints 0 :confused:

Also doing this:

print(httpService:JSONDecode(loadJSON))

prints a table, so I’m guessing that it is saving??

No, print the JSON directly. It’s just to see what’s inside the variable

1 Like
print(httpService:JSONEncode(httpService:JSONDecode(loadJSON)))

does this print the expected value?

@Gagou_Bloxxer

 {"Cash":50,"Mood":"Happy","Items":[[{"Position":[-81.5738983154296875,6.65791416168212890625,-102.1114959716796875,0,0,-1],"ItemName":"Model"}]]}

It seems to be working. So it is saving the models position, etc. But inside the load function, going

print(#user.Items)

it prints 0. So unless it’s cause arrays don’t count or something?? But I don’t know, to me from what I see it should work perfectly

Could it be the way I’m saving the models as well?? It’s hard to read how it’s being saved in a single line, but I want it to be saving as the Model name, and then inside the model name would be it’s values, like so:

[Items] = {
    ['Model'] = {
        ['Poistion'] = -- CFrame (Position + direction)
    }
}

And then in the future I’d add saving of colors, etc. but if I can’t get this basic stuff done then no point trying to make it more complex

As we didn’t develop the game it’s not always easy to see what’s wrong compared to what’s expected to happen.

However, in that case might be in playerData[player.UserId] = updateObject(setData, data), or inside the function updateObject(), try checking that

1 Like
function updateObject(old, new)
local update = {}
for i, v in next, new do
    update[i] = (type(v) == 'table' and old[i] and updateObject(old[i], v)) or old[i] or v
end

return update
end

this is that function. It’s intention was to add in extra stuff to the default players data, so if somebody joins who already has a data save won’t be missing on any new data that was added to the game between their last save.

“Items”:[[{
You’re not saving it as Items > Model > Position, you’re saving it as Items > Random Array > Model > Position. It also seems that the values are initialized which I think may be from it not setting the variables properly, because the JSON is fine, it has to be the loading.

JSON=' {"Cash":50,"Mood":"Happy","Items":[[{"Position":[-81.5738983154296875,6.65791416168212890625,-102.1114959716796875,0,0,-1],"ItemName":"Model"}]]}'
> print(JSON)
 {"Cash":50,"Mood":"Happy","Items":[[{"Position":[-81.5738983154296875,6.65791416168212890625,-102.1114959716796875,0,0,-1],"ItemName":"Model"}]]}
> print(game.HttpService:JSONDecode(JSON).Items)
table: 3D98F098
>  print(#game.HttpService:JSONDecode(JSON).Items)
1

it works for me in command line

I’m trying to use it a seperate function though :confused:

When I go

print(#user.Items)
print(user.Cash)

It now prints the Cash at 50, but not the Items amount. So it is def saving that data, and well I can tell that it’s loading the items, but I’m guessing it’s not being ‘saved’ properly in how I am adding the items.
As mentioned:

But idk why it’s saving a random array. So I’m guessing it has to do with this:

for _, item in pairs(playersPlot.Purchases:GetChildren()) do
		print(item.Name)
		local itemData = {}
		local primaryPart = item.PrimaryPart
		local position = playersPlot.PrimaryPart.CFrame:inverse() * primaryPart.Position
		local direction = primaryPart.CFrame.lookVector
		
		itemData.ItemName = item.Name
		itemData.Position = {
			position.X, 
			position.Y, 
			position.Z, 
			direction.X, 
			direction.Y, 
			direction.Z
		}
		playerItems[#playerItems + 1] = itemData
	end

local user = playerData[player.UserId]
	
	table.insert(user.Items, playerItems)

So the problem seems to be I am now saving the dictionary correctly.

table.insert(user.Items, playerItems)

You’re inserting the playerItems into user.Items. I think what you want is to set user.Items to playerItems. Try user.Items = playerItems

  {"Cash":50,"Mood":"Happy","Items":[{"Position":[-81.5738983154296875,6.654655933380126953125,-102.1114959716796875,0,0,-1],"ItemName":"Model"}]}

However, still printing:

print(#user.Items)

Prints 0

EDIT

Putting the print from within the GetData also returns 0

function dataManager:GetData(player)
	local loadJSON = playerDataStore:GetAsync(player.UserId) or {}
	local setData = httpService:JSONDecode(loadJSON) or {}
	
	print(httpService:JSONEncode(httpService:JSONDecode(loadJSON))) -- the full array
	
	playerData[player.UserId] = updateObject(setData, data)
	local user = playerData[player.UserId]
	
	print('Joining', #user.Items) -- 0
	dataReady = true
end

But the print(httpService:JSONEncode(httpService:JSONDecode(loadJSON))) it still prints the table

I found the problem

function updateObject(old, new)
    local update = {}
    for i, v in next, new do
        update[i] = (type(v) == 'table' and old[i] and updateObject(old[i], v)) or old[i] or v
    end

    return update
end

local loadJSON = playerDataStore:GetAsync(player.UserId) or {}
	local setData = httpService:JSONDecode(loadJSON) or {}
		
	playerData[player.UserId] = setData--updateObject(setData, data)

If I go setData on playerData, it works. The commented out section is what I had before, and with that it breaks. Problem with removing this is if I add some more values to the data store, players who already have saved data won’t be able to get those new values, as they will load in an old data store.

@Gagou_Bloxxer
@bluddbrain
@sonihi

2 Likes