Serialise instances of classes to JSON
Posted: Mon Oct 18, 2021 6:53 pm
I want to export as much live data as possible from Factorio. I'm aiming to create a live map of Factorio, in the style of the Minecraft mod Dynmap. I also hope to make a platform that will be a good basis for some other mods, as well as learning some new tech.
To do this I want to react to Factorio events, and convert objects into a common data format (for example, JSON, although some other common format would be good) to be transferred via file or stdout. I'm new to Lua and Factorio modding! I'm hoping there's a good way to do this.
I'm stuck on converting the object to JSON. I've tried serpent.block(obj), but from what I understand it can only serialise tables. LuaPlayer and LuaEntity are not tables - so the result has no useful information.
The same is true of game.table_to_json(obj), which returns an error.
I can manually create an LuaPlayer-to-Table mapper function, but creating a mapper function for all classes seems like a lot of work! Before I head down that path I'd to ask if there was some other standard method, or available library, to serialise objects?
Here's a sample of what I have so far. The mod receives an event, and produces a number of files (depending on what the event is referring to).
To do this I want to react to Factorio events, and convert objects into a common data format (for example, JSON, although some other common format would be good) to be transferred via file or stdout. I'm new to Lua and Factorio modding! I'm hoping there's a good way to do this.
I'm stuck on converting the object to JSON. I've tried serpent.block(obj), but from what I understand it can only serialise tables. LuaPlayer and LuaEntity are not tables - so the result has no useful information.
Code: Select all
-- result of serpent.block(obj)
{
__self = "userdata"
}
Code: Select all
-- result of game.table_to_json(obj)
Value (userdata) can't be saved in property tree at ROOT.__self
Here's a sample of what I have so far. The mod receives an event, and produces a number of files (depending on what the event is referring to).
Code: Select all
-- receive event from Factorio
script.on_event(
defines.events.on_player_mined_entity,
function(e)
entityEvent(e.tick, e.entity, "on_player_mined_entity")
playerEvent(e.tick, e.player_index, "on_player_mined_entity")
end
)
-- serialise valid Entity event updates
function entityEvent(tick, entity, eventType)
if (entity.unit_number ~= nil) and (entity.unit_number ~= 0) then
local ____ = entity[""]
local filename = table.concat({entity.unit_number, eventType, tick}, "_")
outputEventFile((entity.object_name .. "/") .. filename, entity)
end
end
-- serialise valid player updates, along with the player's character(s)
function playerEvent(tick, player_index, eventType)
local player = game.players[player_index]
local filename = table.concat({player.index, eventType, tick}, "_")
outputEventFile((player.object_name .. "/") .. filename, player)
if player.character ~= nil then
entityEvent(tick, player.character, eventType)
for ____, char in ipairs(
player.get_associated_characters()
) do
if char ~= nil then
entityEvent(tick, char, eventType)
end
end
end
end
-- write event to disk (TODO use stdout instead)
function outputEventFile(filename, obj)
local data = serpent.block(obj) -- doesn't work
game.write_file((EVENT_FILE_DIR .. "/") .. filename, data, false, 0)
end