Struggling to get JSONDecode to work properly

Hey! I am trying to write a global banning script for one of my games. I’m using MessagingService once the player gets marked as banned to check in every server if the player is playing (to remove them from the game.) After I use JSONEncode to make the info work with MessagingService, trying to decode it seems to not be working properly. The error I get is here:

Error

I have a Banning ModuleScript that is required by a BanHandler.
The BanHandler script goes as follows:

local banModule = require(script.Parent.BanModule)
local msgService = game:GetService("MessagingService")
local httpService = game:GetService("HttpService")
local pls = game:GetService("Players")

msgService:SubscribeAsync("Bans", function(message)
	local data = httpService:JSONDecode(message)
	local bannedStatus = data.Banned
	local userId = data.UserID
	local username = pls:GetNameFromUserIdAsync(tonumber(userId))
	if pls:FindFirstChild(username) and bannedStatus then
		pls[username]:Kick("Banned.")
	end
end)

The Ban Module goes as following:

    local module = {}

local DataStore = game:GetService("DataStoreService")
local msgService = game:GetService("MessagingService")
local httpService = game:GetService("HttpService")
local banStore = DataStore:GetDataStore("New Data 5")

function loadData(UserId)
	local data
	local success = pcall(function()
		data = banStore:GetAsync(tostring(UserId))
	end)
	if(not success)then
		wait(60)
		loadData(UserId)
	end
	print("Player data grabbed")
	return data
end

function module.BanPlayer(id)
	local data = loadData(id)
	if not data.BannedInformation then
		data.BannedInformation = {
			Banned = false
		};
	end
	data.BannedInformation = {
		Banned = true,
	};
	print("Ban set.")
	banStore:SetAsync(id, data)
	print("Ban published")
	local msgData = {
		UserID = id;
		Banned = true;
	};
	local encoded = httpService:JSONEncode(msgData)
	print(encoded)
	msgService:PublishAsync("Bans", encoded)
end


return module

Here’s the entire output:
Output

Thank you for any help, I’m sure this is a very dumb and simple issue.

1 Like

This has me befuddled, the only thing I can think of is that somewhere along the way in being transmitted thru messagingservice the string somehow becomes malformed? Mind adding print("received: ", message) to the top of the subscribeasync callback and showing the output?

1 Like

Sure thing.
newinfo

I may know the issue, but I’m not completely sure. At this point I think it’s because of how I’m calling the ban. I am currently in the testing phase, so I’m using the developer console to execute the command by doing:

local banModule = require(game.ServerScriptService.BanModule)
banModule.BanPlayer(1100753439)

This could be affecting it, which I am presuming it is. I will look more into this later tonight when I am able to get back on.

Well that’s certainly odd, it seems like messaging service is turning it back into a table somewhere along the line! I’d traverse it and see if it’s formed as expected (i.e. as it was prior to being encoding).

Just checked myself, it seems as if messaging service passes it as a table which has a Data property equal to the data published.
image

This might be intended? I’m not sure since I’m not familiar with the service and the documentation is, er, borked


In any case, just change line seven to

local data = httpService:JSONDecode(message.Data)
1 Like

Interesting issue
can you print the message right before you JSON decode it in the first script

Here’s the link. Unfortunately the actual entry for SubscribeAsync does not tell you anything about the payload but the link above does:

The callback function for SubscribeAsync() receives a table, not a string. This table contains both message.Data (the developer-defined data sent via PublishAsync()) and message.Sent which is the Unix time in seconds at which the message was sent.

1 Like

Thanks, it appears they misformatted the links on the SubscribeAsync and PublishAsync pages since those both lead to https://developer.roblox.com/en-us/api-reference/function/MessagingService/articles/cross-server-messaging and not https://developer.roblox.com/en-us/articles/cross-server-messaging.

1 Like

You don’t need to encode or decode the data your passing as Roblox does it by default. You’re basically double encoding/decoding for no reason.

local data = httpService:JSONDecode(message)

This is most likely why your script is erroring. You’re trying to decode a dictionary passed by Roblox that’s not even encrypted in the first place. This dictionary contains two keys, ‘Data’ (in this case, your bans table), and ‘Sent’ in which the time the message was sent. Directly referencing to message.Data should work.

local data = message.Data

Make sure to get rid of the JSONEncode and JSONDecode as Roblox already does that for you!

3 Likes