Can't parse json

  1. What do you want to achieve? Keep it simple and clear!

I am trying to use roblox’s catalog api to get a list of audios based on the input the player gives.

  1. What is the issue? Include screenshots / videos if possible!

When I try to JSONDecode the given data it says “Can’t parse JSON”.

  1. What solutions have you tried so far? Did you look for solutions on the Developer Hub?

I have tried looking at devforum and found people who ran into the same problem but I wasn’t able to figure how to fix it.

-- Services
local httpService = game:GetService("HttpService")
local contentProvider = game:GetService("ContentProvider")
local tweenService = game:GetService("TweenService")
local marketPlaceService = game:GetService("MarketplaceService")

-- Modules
local proxyService = require(game.ServerScriptService:WaitForChild("ProxyService"))
local proxy = proxyService:New("https://musicplayer1001.herokuapp.com/", "ACCESS_KEY HIDDEN")
local Loading = require(script.Parent.Loading)

-- Player
local player = script.Parent.Parent.Parent.Parent
local InMPFolder = player:WaitForChild("InMP")
local Playlists = InMPFolder:WaitForChild("Playlists")

-- Event
local SearchEvent = script.Parent.Parent.Events.Search
local TweenOnClient = script.Parent.Parent.Events.TweenOnClient
local PlayMusic = script.Parent.Parent.Events.PlayMusic

local PlaylistEvents = game.ReplicatedStorage.PlaylistsEvents

-- Frames
local Topbar = script.Parent.Parent.MainFrame.Topbar
local BodyFrame = script.Parent.Parent.MainFrame.Body
local Modules = BodyFrame.Modules

local Templates = script.Parent.Parent.Templates
local ResultTemplate = Templates.ResultsTemplate
local OptionTemplate = Templates.OptionTemplate

-- Values
local originalLink = "https://search.roblox.com/catalog/json?CatalogContext=2&Category=9&SortType=2"
local updatedLink = ""
local CurrentSelectedPlaylist = ""

local connectFunction = {}

function updateLink(keyword, creatorId)
	if keyword then
		updatedLink = originalLink .. '&Keyword="' .. keyword .. '"'
		BodyFrame.Pages.Search.Title.Text = '"' .. keyword .. '"'
	elseif creatorId then
		updatedLink= originalLink .. "&CreatorID=" .. creatorId
		BodyFrame.Pages.Search.Title.Text = "Your Audio"
	end
end

-- Call this function to set events for each search result
function setEvents(frame, songData)
	-- Event for when the player wants to add the current song to their playlist
	frame.Add.MouseButton1Down:Connect(function()
		-- Clear all options to the dropdown of this frame
		for i, v in pairs(Modules.AddToPlaylists.Dropdown.Options:GetChildren()) do
			if v:IsA("TextButton") then
				v:Destroy()
			end
		end		
		
		
		Modules.AddToPlaylists.Dropdown.CurrentOption.Text = "None selected"
		CurrentSelectedPlaylist = ""
		
		-- Now add new options to the dropdown
		for name, list in pairs(httpService:JSONDecode(Playlists.Value)) do
			local newOption = OptionTemplate:Clone()
			newOption.Name = name
			newOption.Text = name
			newOption.Visible = true
			newOption.Parent = Modules.AddToPlaylists.Dropdown.Options
			
			newOption.MouseButton1Down:Connect(function()
				Modules.AddToPlaylists.Dropdown.CurrentOption.Text = name
				CurrentSelectedPlaylist = name
			end)
		end
		
		TweenOnClient:FireClient(player, Modules.AddToPlaylists, "Position", UDim2.new(0.249, 0, 0.252, 0), "In", "Linear", 0.2, false)
		Modules.AddToPlaylists.Song.Text = songData.Name
		-- Disconnect old event
		if connectFunction["AddToPlaylistButton"] then
			connectFunction["AddToPlaylistButton"]:Disconnect()
		end
		-- Connect new function
		connectFunction["AddToPlaylistButton"] = Modules.AddToPlaylists.Add.MouseButton1Down:Connect(function()
			if CurrentSelectedPlaylist ~= "" then
				local success, message = PlaylistEvents.AddToPlaylist:Invoke(player, CurrentSelectedPlaylist, songData.AssetId)
				
				if success then
					TweenOnClient:FireClient(player, Modules.AddToPlaylists, "Position", UDim2.new(0.249, 0,1.17, 0), "Out", "Linear", 0.2, false)
					frame:Destroy()
				else
					BodyFrame.AddToPlaylists.Error.Text = message
					wait(2)
					BodyFrame.AddToPlaylists.Error.Text = ""
				end
				
				-- Disconnect event
				connectFunction["AddToPlaylistButton"]:Disconnect()
			end
		end)
	end)
	
	frame.BottomFrame.Resume.MouseButton1Down:Connect(function()
		PlayMusic:FireClient(player, songData, true, frame)
	end)
	
	frame.BottomFrame.Pause.MouseButton1Down:Connect(function()
		PlayMusic:FireClient(player, songData, false, frame)
	end)
end

-- Data first parameter is when you have searched and got the result. Second Parameter is when you have searched by sound ID
function addFrames(data, secondData)
	if data then
		for _, sound in pairs(data) do
			-- Create New Frame
			local newFrame = ResultTemplate:Clone()
			newFrame.Name = sound.Name
			newFrame.Parent = BodyFrame.Pages.Search.Results
			newFrame.Visible = true

			-- Update Stats
			newFrame.MusicTitle.Text = sound.Name
			newFrame.BottomFrame.Artist.Text = sound.Creator

			setEvents(newFrame, sound)
			-- Increase Canvas Size
		end
	elseif secondData then --< Else if Its a sound Id then we just create one separate frame
		local newFrame = ResultTemplate:Clone()
		newFrame.Name = secondData.Name
		newFrame.Parent = BodyFrame.Pages.Search.Results
		newFrame.Visible = true
		
		-- Update Stats
		newFrame.MusicTitle.Text = secondData.Name
		newFrame.BottomFrame.Artist.Text = secondData.Creator.Name
		
		setEvents(newFrame, secondData)
	end
end

SearchEvent.OnServerEvent:Connect(function(player, inputedText, isMyAudio)
	-- First, start the loading
	local loading = Loading.renderLoadingCircle(BodyFrame.Pages.Search)
	
	-- Second, Destroy Recent Search Results and Update Canvas
	for i, v in pairs(BodyFrame.Pages.Search.Results:GetChildren()) do
		if v:IsA("Frame") then
			v:Destroy()
		end
	end

	local request = nil
	
	-- Third, Update Link and Send Request
	if isMyAudio then
		updateLink(nil, player.UserId)
		request = proxy:Get(updatedLink)
		loading.stop()
		addFrames(httpService:JSONDecode(request.body))
	else
		if typeof(tonumber(inputedText)) == "number" then
			-- First try to see if its a sound Id
			local data = nil
			local isNotASoundID = false
			local success = pcall(function()
				data = marketPlaceService:GetProductInfo(tonumber(inputedText), Enum.InfoType.Asset) 
				
				if data then
					if data.AssetTypeId == 3 then
					else
						isNotASoundID = true
					end
				end
			end)
			
			-- If it isn't a sound Id then return a message saying so
			if isNotASoundID or success == false then
				BodyFrame.Pages.Search.Title.Text = "The requested ID is not a sound ID"
				loading.stop()
				wait(2)
				BodyFrame.Pages.Search.Title.Text = "Results"
				return
			end
			
			-- If data isn't equal to nil then we found a sound else its a creator ID
			if  data then
				BodyFrame.Pages.Search.Title.Text = "Sound ID: " .. data.AssetId
				addFrames(nil, data)
				loading.stop()
			end
		else
			updateLink(inputedText)
			local request = proxy:Get(updatedLink)
			addFrames(httpService:JSONDecode(request.body))
			loading.stop()
		end
	end
end)

Any help is appreciated

Thanks,
Indelton

1 Like

First thing you should be checking is if the returned value is in JSON format in the first place then rather than assuming that your HTTP call will return a 2xx status code and a JSON formatted value.

1 Like

As @colbert2677 said you want to for example see what it returns

So try to print out request and request.body
I assume the body is empty or not valid to be decoded into JSON
image

You might want to check out
HttpService:JSONDecode
HttpService
• Does the proxy work?

Sorry for responding late.
I did try to print out request and I got this

{
                    ["body"] = "<html><head><title>Object moved</title></head><body>
<h2>Object moved to <a href="https://www.roblox.com/request-error?id=504d74e2-f1a6-4983-bcbf-b47e284d20a5&amp;mode=&amp;code=">here</a>.</h2>
</body></html>
",
                    ["headers"] =  ▶ {...},
                    ["status"] =  ▶ {...}
                 }

It doesn’t work even If I enter something else. It returns the same thing (^ above JSON Format).

I just tried going to Create → Library → Audio and I get this error “Library temporarily unavailable, please try again later.”. So I think its roblox’s audio api and not the script.

Edit: Audio Library was unavailable for a few days. Its working now