Skip to content

Commit

Permalink
Add 'minetest.write_json'
Browse files Browse the repository at this point in the history
  • Loading branch information
ShadowNinja committed Dec 18, 2013
1 parent 49cec3f commit 1ed90c9
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 1 deletion.
11 changes: 10 additions & 1 deletion doc/lua_api.txt
Expand Up @@ -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
Expand Down
49 changes: 49 additions & 0 deletions src/script/common/c_content.cpp
Expand Up @@ -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
}

3 changes: 3 additions & 0 deletions src/script/common/c_content.h
Expand Up @@ -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[];

Expand Down
27 changes: 27 additions & 0 deletions src/script/lua_api/l_util.cpp
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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);
Expand Down
3 changes: 3 additions & 0 deletions src/script/lua_api/l_util.h
Expand Up @@ -64,6 +64,9 @@ class ModApiUtil : public ModApiBase {
// 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);

Expand Down

0 comments on commit 1ed90c9

Please sign in to comment.