The following little snippet allows you to ‘pickle’ Lua objects directly into Lua code (with the exception of functions, which are serialized as raw bytecode). Metatable support is on the way, but for now, it should be useful enough.
Example code:
01.
dofile
?"pickle.lua"
02.
? 03.
users?
=
?{
04.
user1?
=
?{
pass?
=
?"abcdef"
,
?start?
=
?10230
}
,
05.
user2?
=
?{
pass?
=
?"cdefba"
,
?start?
=
?12032
}
06.
}
07.
? 08.
userdump?
=
?pickle
.
dumps
(
users
)
09.
print
(
userdump
)
Outputs
01.
return
?{
02.
[
"user1"
]
?=
?{
03.
[
"pass"
]
?=
?"abcdef"
,
04.
[
"start"
]
?=
?10230
,
05.
}
,
06.
[
"user2"
]
?=
?{
07.
[
"pass"
]
?=
?"cdefba"
,
08.
[
"start"
]
?=
?12032
,
09.
}
,
10.
}
Pickle API:
- pickle.dumps(object) -> String
Pickles an object and returns it.
- pickle.dump(object, filename) -> String
Pickles an object and saves it as :filename, afterwards, returns the dump.
- pickle.loads(object) -> Lua Object
Loads a string dump of lua object and returns the object. The returned object will not injected into the global table.
- pickle.load(filename) -> Lua Object
Loads a pickled object from a file and returns it. The returned object will not be injected into the global table.
Full Source:
01.
local
?objects?
=
?{
}
02.
setmetatable
(
objects
,
?{
__index
=
{
[
"subset"
]
=
function
(
object
,
?proxies
)
03.
for
?_
,
o in?
ipairs
(
proxies
)
?do
04.
if
?object?
=
=
?o?
then
?return
?true
?end
05.
end
06.
end
}
}
)
07.
? 08.
function
?_pickle
(
object
,
?seen
,
?indent
)
09.
-
--if not seen then seen = {} end
10.
if
?not
?indent?
then
?indent?
=
?""
?end
11.
? 12.
local
?serialize_key?
=
?function
(
key
)
13.
if
?type
(
key
)
?=
=
?"string"
?then
14.
return
?"[\""
..
key
..
"\"]"
15.
elseif
?type
(
key
)
?=
=
?"table"
?then
16.
return
?"["
..
_pickle
(
key
)
:gsub
(
"\n"
,
" "
)
..
"]"
17.
else
18.
return
?"["
..
key
..
"]"
19.
end
20.
return
?key
21.
end
22.
? 23.
local
?escape?
=
?function
(
o
)
24.
return
?o:gsub
(
"\\","
\\\\
"):gsub("
'","\\'"):gsub('
"
','
\\"'
)
25.
end
26.
? 27.
-
--Switch Object type:
28.
if
?type
(
object
)
?=
=
?"table"
?then
29.
local
?serialize?
=
?"{\n"
30.
for
?key
,
?value in pairs
(
object
)
?do
31.
serialize?
=
?serialize?
..
?indent
..
"\t"
?..
?serialize_key
(
key
)
?..
?" = "
?..
tostring
(
_pickle
(
value
,
?seen
,
?indent
..
"\t"
)
)
?..
?",\n"
32.
end
33.
serialize?
=
?serialize?
..
?indent?
..
?"}"
34.
? 35.
return
?serialize
36.
elseif
?type
(
object
)
?=
=
?"string"
?then
37.
return
?'"'
?..
?escape
(
object
)
?..
?'"'
38.
elseif
?type
(
object
)
?=
=
?"function"
?then
39.
return
?"loadstring([["
..
string.dump
(
object
)
..
"]])"
40.
elseif
?objects
.
subset
(
object
,
?{
"userdata"
}
)
?then
41.
return
?nil
42.
end
43.
return
?tostring
(
object
)
44.
end
45.
? 46.
pickle?
=
?{
}
47.
? 48.
function
?pickle
.
dumps
(
object
)
49.
return
?"return "
..
?_pickle
(
object
)
50.
end
51.
? 52.
function
?pickle
.
dump
(
object
,
?filename
)
53.
local
?dump?
=
?pickle
.
dumps
(
object
)
54.
local
?_file?
=
?io.open
(
filename
,
?"wb"
)
55.
_file:write
(
dump
)
56.
_file:close
(
)
57.
return
?dump
58.
end
59.
? 60.
function
?pickle
.
loads
(
object
)
61.
local
?fn?
=
?loadstring
(
object
)
62.
if
?fn?
then
63.
return
?fn
(
)
64.
end
65.
end
66.
? 67.
function
?pickle
.
load
(
filename
)
68.
local
?_file?
=
?io.open
(
filename
,
?"rb"
)
69.
local
?dump?
=
?_file:read
(
"*all"
)
70.
local
?object?
=
?pickle
.
loads
(
dump
)
71.
_file:close
(
)
72.
return
?object
73.
end