Simply put I have a script similar to this-->
01 | local maintable = { } |
02 | local addtable = { "Stuff" , "MoreStuff" } |
03 | local metatable = { "MoreMoreStuff" , "ExtraMoreStuff" } |
04 | setmetatable (addtable,metatable) |
05 | table.insert(maintable, 1 ,addtable) |
06 |
07 |
08 | local DataStore = game:GetService( "DataStoreService" ):GetDataStore( "FakeDataStore" ) |
09 | local http = game:GetService( "HttpService" ) |
10 | local JSON = http:JSONEncode(maintable) |
11 | DataStore:SetAsync( "JsonSave" ,JSON) |
The whole thing works fine and when I load the JSON again I have everything... except the meta table. I try-->
01 | --Of course not in the same script |
02 | local DataStore = game:GetService( "DataStoreService" ):GetDataStore( "FakeDataStore" ) |
03 | local LoadedMainTable = DataStore:GetAsync( "JsonSave" ) |
04 | local Decodedtable = http:JSONDecode(LoadedMainTable) |
05 | local addtable = Decodedtable [ 1 ] |
06 | if addtable then |
07 | local metatable = getmetatable (addtable) |
08 | if metatable then |
09 | print ( "GotMetaTable" ) |
10 | else |
11 | print ( "--MetaTable = nil" ) |
12 | end |
13 | end |
This script results in this in the output-->
1 | --MetaTable = nil |
So my question is: Does JSONEncode/Decode get ride of all meta tables? If not then how would you successfully get a meta table from a decoded JSON format?
Metatables can't be meaningfully serialized (turned into text) because they have functions attached to them. (This is documented)
This is impossible because functions can be closures--they can refer to particular variables ruining in the program, which doesn't make sense to give to someone on another computer.
I would suggest making an extra property recording the "type" of the thing, and looking up the appropriate metatable and then applying it.
Here is an example of the kind of thing I am suggesting:
01 | function setupHouse(data) |
02 | setmetatable (data, houseMeta) |
03 | end |
04 |
05 | function setupLine(data) |
06 | setmetatable (data, lineMeta) |
07 | end |
08 |
09 | -- `data` is the result of DecodeJSON. |
10 | -- It attaches the appropriate metatable |
11 | function receiveData(data) |
12 | if data. type = = "house" then |
13 | setupHouse(data) |
14 | elseif data. type = = "line" then |
15 | setupLine(data) |
16 | elseif ... etc then |
17 |
18 | end |
19 | end |
Then you have to remember that when you serialize to JSON, you have to include the proper .type
property.
You can shorten all of the elseif
s using a dictionary:
01 | local metas = { |
02 | house = houseMeta, |
03 | line = lineMeta, |
04 | dog = dogMeta, |
05 | -- etc |
06 | } |
07 |
08 | function receiveData(data) |
09 | local meta = metas [ data. type ] |
10 | if meta then |
11 | setmetatable (data, meta) |
12 | end |
13 | end |
14 |
15 | -- adds the `.type` property to `.data`, which is an object with (maybe) a metatable |