Add 'minetest.write_json'

This commit is contained in:
ShadowNinja 2013-12-18 16:46:53 -05:00
parent 49cec3f782
commit 1ed90c90c3
5 changed files with 92 additions and 1 deletions

View File

@ -1530,7 +1530,16 @@ minetest.parse_json(string[, nullvalue]) -> something
^ nullvalue: returned in place of the JSON null; defaults to nil
^ On success returns a table, a string, a number, a boolean or nullvalue
^ On failure outputs an error message and returns nil
^ Example: parse_json("[10, {\"a\":false}]") -> {[1] = 10, [2] = {a = false}}
^ Example: parse_json("[10, {\"a\":false}]") -> {10, {a = false}}
minetest.write_json(data[, styled]) -> string
^ Convert a Lua table into a JSON string
^ styled: Outputs in a human-readable format if this is set, defaults to false
^ Un-serializable things like functions and userdata are saved as null.
^ Warning: JSON is more strict than the Lua table format.
1. You can only use strings and positive integers of at least one as keys.
2. You can not mix string and integer keys.
This is due to the fact that Javascript has two distinct array and object values.
^ Example: write_json({10, {a = false}}) -> "[10, {\"a\": false}]"
minetest.serialize(table) -> string
^ Convert a table containing tables, strings, numbers, booleans and nils
into string form readable by minetest.deserialize

View File

@ -1081,3 +1081,52 @@ bool push_json_value(lua_State *L, const Json::Value &value, int nullindex)
else
return false;
}
// Converts Lua table --> JSON
void get_json_value(lua_State *L, Json::Value &root, int index)
{
int type = lua_type(L, index);
if (type == LUA_TBOOLEAN) {
root = (bool) lua_toboolean(L, index);
} else if (type == LUA_TNUMBER) {
root = lua_tonumber(L, index);
} else if (type == LUA_TSTRING) {
size_t len;
const char *str = lua_tolstring(L, index, &len);
root = std::string(str, len);
} else if (type == LUA_TTABLE) {
lua_pushnil(L);
while (lua_next(L, index)) {
// Key is at -2 and value is at -1
Json::Value value;
get_json_value(L, value, lua_gettop(L));
Json::ValueType roottype = root.type();
int keytype = lua_type(L, -1);
if (keytype == LUA_TNUMBER) {
lua_Number key = lua_tonumber(L, -1);
if (roottype != Json::nullValue && roottype != Json::arrayValue) {
throw LuaError(NULL, "Can't mix array and object values in JSON");
} else if (key < 1) {
throw LuaError(NULL, "Can't use zero-based or negative indexes in JSON");
} else if (floor(key) != key) {
throw LuaError(NULL, "Can't use indexes with a fractional part in JSON");
}
root[(Json::ArrayIndex) key - 1] = value;
} else if (keytype == LUA_TSTRING) {
if (roottype != Json::nullValue && roottype != Json::objectValue) {
throw LuaError(NULL, "Can't mix array and object values in JSON");
}
root[lua_tostring(L, -1)] = value;
} else {
throw LuaError(NULL, "Lua key to convert to JSON is not a string or number");
}
}
} else if (type == LUA_TNIL) {
root = Json::nullValue;
} else {
throw LuaError(NULL, "Can only store booleans, numbers, strings, objects, arrays, and null in JSON");
}
lua_pop(L, 1); // Pop value
}

View File

@ -150,6 +150,9 @@ void luaentity_get (lua_State *L,u16 id);
bool push_json_value (lua_State *L,
const Json::Value &value,
int nullindex);
void get_json_value (lua_State *L,
Json::Value &root,
int index);
extern struct EnumString es_TileAnimationType[];

View File

@ -179,6 +179,32 @@ int ModApiUtil::l_parse_json(lua_State *L)
return 1;
}
// write_json(data[, styled]) -> string
int ModApiUtil::l_write_json(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
bool styled = false;
if (!lua_isnone(L, 2)) {
styled = lua_toboolean(L, 2);
lua_pop(L, 1);
}
Json::Value root;
get_json_value(L, root, 1);
std::string out;
if (styled) {
Json::StyledWriter writer;
out = writer.write(root);
} else {
Json::FastWriter writer;
out = writer.write(root);
}
lua_pushlstring(L, out.c_str(), out.size());
return 1;
}
// get_dig_params(groups, tool_capabilities[, time_from_last_punch])
int ModApiUtil::l_get_dig_params(lua_State *L)
{
@ -249,6 +275,7 @@ void ModApiUtil::Initialize(lua_State *L, int top)
API_FCT(setting_save);
API_FCT(parse_json);
API_FCT(write_json);
API_FCT(get_dig_params);
API_FCT(get_hit_params);

View File

@ -64,6 +64,9 @@ private:
// parse_json(str[, nullvalue])
static int l_parse_json(lua_State *L);
// write_json(data[, styled])
static int l_write_json(lua_State *L);
// get_dig_params(groups, tool_capabilities[, time_from_last_punch])
static int l_get_dig_params(lua_State *L);