Show me what the table looks like that you’re trying to send over?
I have multiple different tables that encounter this issue, this isn’t a problem limited to one specific table.
Why do you have mixed tables? There are few cases where I find mixed tables to actually be the right design choice. Could you break up these tables into nested tables with sequential and referential parts? What is just one example where you are having trouble sending a mixed table?
Ultimately, the issue probably lies in the fact that you are mixed data structures. A mixed index table isn’t really a true data structure. You are combining an array with a map and that really doesn’t make sense from a computer science perspective.
Yeah, I have to agree with @TheNickmaster21 on this. It’s pretty easy to design structures that avoid mixed tables.
I can’t think of any real-world applications where a mixed table-like structure is used.
It’s mostly nil values causing the issues, and the fact that you can’t do { { X = 1, X = 2 }, { X = 1, X = 2 }
You should be able to do that. A mixed table only relates to the immediate table, not sub-tables. I’ve done it many times with DataStores and such.
Interesting, not sure what was causing the error then! I’ll do some tests and post here when I’m done.
This is incorrect, all sub-tables (and sub-sub-tables, and sub-sub-sub, etc…) need to be non-mixed right now. The property applies to the entire structure of tables, not just top-level. (This is most likely because it is marshalled into JSON internally)
> workspace.Event:Fire(
{
"hello",
{
[2] = "world",
[5] = "!!!"
}
}
)
18:02:44.507 - Cannot convert mixed or non-array tables: keys must be strings
This is the table I’m having issues with:
{ [ 2 ] = { 1, 2 } }
Don’t have the issue with this though
{ nil, { 1, 2 } }
As a temporary workaround, if your keys can only be numbers, you can just tostring the indices that you set and then turn them back into numbers at the receiving end.
That’s because in the first example, you have an array of numerical indices but it doesn’t start at 1 (and also it may have no holes, if there were multiple indices). In the second example, you don’t supply any indices, so it just becomes an array which is allowed.
Yet { 1, 2, 3, B = 1 } works?
I think I may be misunderstanding what a mixed table is?
If you actually print the result of that table being passed through a Bindable/RemoteEvent, you’d find that the B = 1 probably got cut off. That’s Roblox’s mistake for not throwing an error there.
Figured out I can use the following function to make it work for now:
local function Fill( Table, a, max )
a = a or 1
if not max then
max = 1
for a, b in pairs( Table ) do
max = math.max( max, a )
end
end
if a > max then return end
return Table[ a ], Fill( Table, a + 1, max )
end
and then
Event:Fire( { Fill{ [ 2 ] = { 1, 2 } } )
-- Original
{ [ 2 ] = { 1, 2 } }
-- New
{ [ 2 ] = { 1, 2 } }
Ok, weird, that must be an issue with Remote/BindableEvents, because it definitely works in DataStores.
This code demonstrates the culling that will occur.
local bindable = Instance.new("BindableEvent")
local function printTable(tab, depth)
depth = depth or 0
local indent = string.rep("\t", depth)
for i, v in pairs(tab) do
if type(v) == "table" then
print(indent .. i .. " : {")
printTable(v, depth + 1)
print(indent .. "}")
else
print(indent .. i .. ": " .. tostring(v))
end
end
end
bindable.Event:Connect(printTable)
bindable:Fire({ 1, 2, 3, B = 1 })
Output:
1: 1
2: 2
3: 3
Made a bug report for this
This is by design, the wiki states
If a Table is passed as an argument to a BindableEvent it must be an array without missing entries or have string keys, not a mixture, or else the string keys will be lost.
Personally feel like this is a bug, if it’s going to be culling keys it should either error or warn to let us know. It errors for other cases.
local tab = {};
tab[1] = 1;
tab[2] = 2;
tab[3] = 3;
-- tab[4] = 4;
tab[2] = nil;
print(game.HttpService:JSONEncode(tab));
Run this and it will give you [1]
. It should give you [1, null, 3]
. Now uncomment the commented line. It will give you [1, null, 3, 4]
as expected.
Note that this affects DataStores and RemoteFunctions/RemoteEvents. Please fix soon.
Yet the following code works:
script.Event.Event:connect( function ( t )
for a, b in pairs( t ) do print( a, b ) end
end )
script.Event:Fire( { 1, nil, 3 } )
>1 1
>3 3