[C++] 纯文本查看 复制代码
/*********************************************
--作者: 小冰哟
--游戏: [email]lovingxiaobing@qq.com[/email]
--备注: Json11非原创,
-- Json11是Github上的一个Json解释器项目
-- 小冰的LJson是对Json11的 一个封装.
--Json11: https://github.com/dropbox/json11
**********************************************/
#include "LJson.hpp"
#pragma comment(lib, "lua53.lib")
/// 其他一般类型的值压入Lua调用栈
void insert_value_in_table(lua_State* L, const json11::Json& json_in_value) {
switch (json_in_value.type()) {
case json11::Json::Type::NUMBER:
{
///数值
lua_pushnumber(L, (lua_Number)(json_in_value.number_value()));
}
break;
case json11::Json::Type::BOOL:
{
///布尔值
lua_pushboolean(L, (int)(json_in_value.bool_value()));
}
break;
case json11::Json::Type::STRING:
{
///字符串
const std::string& str_in_json = json_in_value.string_value();
lua_pushlstring(L, str_in_json.c_str(), str_in_json.length());
}
break;
case json11::Json::Type::NUL:
{
///空值(NULL)
lua_pushnil(L);
}
break;
default:
break;
}
}
///将Json11对象转换为lua表
void ParseJson11ToLuaTable(
lua_State* L,
const json11::Json& json_object,
int tb_index,
int& lua_stack_length) {
///预留至少三个空闲元素空间(Lua调用栈)
if (lua_stack_length - lua_gettop(L) < 3) {
lua_checkstack(L, 3);
lua_stack_length += 3;
}
///判断是否是可迭代对象
switch (json_object.type()) {
/// 数组或者Json对象
case json11::Json::Type::ARRAY:
{
const json11::Json::array& arr = json_object.array_items();
/// 创建一张足够容量的空表
lua_createtable(L, arr.size(), 0);
int now_tb_index = lua_gettop(L);
lua_pushstring(L, "__name");
lua_pushstring(L, LJSON_ARRAY);
lua_rawset(L, now_tb_index);
for (size_t index = 0; index < arr.size(); ++index) {
///获取数组内容
const json11::Json& json_in_value = json_object[index];
///如果是可迭代对象,递归这个对象
if (json_in_value.is_array() || json_in_value.is_object()) {
/// 执行后获得到的值在栈顶
ParseJson11ToLuaTable(L, json_in_value, now_tb_index, lua_stack_length);
} else {
///是其他的一般类型
insert_value_in_table(L, json_in_value);
}
/// Lua数组第一个元素是1
lua_rawseti(L, now_tb_index, (lua_Integer)(index+1));
}
///!若是空数组则表内无元素
}
break;
case json11::Json::Type::OBJECT:
{
///是个不可描述的对象(key-value)
const json11::Json::object& j_obj = json_object.object_items();
lua_createtable(L, j_obj.size(), 0);
int now_tb_index = lua_gettop(L);
lua_pushstring(L, "__name");
lua_pushstring(L, LJSON_OBJECT);
lua_rawset(L, now_tb_index);
for (const auto& kv: j_obj) {
const std::string& key = kv.first;
const json11::Json& value = kv.second;
lua_pushstring(L, key.c_str());
if (value.is_array() || value.is_object()) {
ParseJson11ToLuaTable(L, value, now_tb_index, lua_stack_length);
} else {
insert_value_in_table(L, value);
}
/// 插入key-value, value位于栈顶
lua_rawset(L, now_tb_index);
}
}
break;
default:
{
///其他类型
insert_value_in_table(L, json_object);
size_t random_index = lua_rawlen(L, tb_index);
lua_rawseti(L, tb_index, (lua_Integer)(++random_index));
}
break;
}
}
///从文件加载
///参数1: JSON数据(文本文件)的路径
///LJson_load 调用 LJson_loads 进行解析,返回值与LJson_loads一样
int LJson_load(lua_State* L) {
const char* json_file = luaL_checkstring(L, 1);
///POSIX标准
///检查文件是否存在
if (!access(json_file, F_OK)) {
///判断文件是否可读
if (access(json_file, R_OK)) {
luaL_error(L, "No Reading access: %s\n", json_file);
}
} else {
luaL_error(L, "No found: %s\n", json_file);
}
///打开文件(文本方式和只读)
std::fstream fs_json(json_file, std::ios::in);
if (false == fs_json.is_open()) {
luaL_error(L, "Json File Open Error!\n");
}
std::stringstream buf;
///读入文件
buf<<fs_json.rdbuf();
if (!fs_json.good())
luaL_error(L, "\"%s\" Read Error!", json_file);
///将读入的JSON字符串压入Lua调用栈
lua_settop(L, 0);
std::string json_str = buf.str();
lua_pushlstring(L, json_str.c_str(), json_str.length());
int LJson_loads(lua_State* L);
return LJson_loads(L);
}
///参数1: JSON字符串
///返回值: 与JSON结构相同但"键-值"顺序不一定相同的的table
int LJson_loads(lua_State* L) {
const char* c_json_str = luaL_checkstring(L, 1);
//从获取的JSON字符串解析成Json11对象
std::string err;
json11::Json LJson_Object = json11::Json::parse(std::string(c_json_str), err);
lua_settop(L, 0);
if (LJson_Object.is_object() || LJson_Object.is_array()) {
///JSON根节点(lua表)
lua_newtable(L);
///给定一个lua调用栈的默认大小
int stk_len = LUA_MINSTACK;
ParseJson11ToLuaTable(L, LJson_Object, 1, stk_len);
} else {
luaL_error(L, "Error: %s\n", err.c_str());
}
///只有成功,不许失败
return 1;
}
///检查元素类型
LJSON_ITERATOR_OBJECT_TYPE check__name_key(lua_State* L, int ele_index) {
const char* key = "__name";
const char* cp_value = LJSON_ARRAY;
/// 首先得是一张表
if (lua_istable(L, ele_index)) {
///获取当前栈顶位置,方便恢复
int before_top = lua_gettop(L);
///如果__name的值是字符串类型则进行进一步判断是否是"LJSON_ARRAY"
if (LUA_TSTRING == lua_getfield(L, ele_index, key)) {
const char* value = lua_tostring(L, lua_gettop(L));
///如果value==cp_value成立则为"LJSON_ARRAY",否则默认为"LJSON_OBJECT"
if (0 == strcmp(value, cp_value)) {
lua_settop(L, before_top);
return I_LJSON_ARRAY;
}
}
lua_settop(L, before_top);
/// "LJSON_OBJECT",nil默认为"LJSON_OBJECT"
return I_LJSON_OBJECT;
}
///不是表则为默认类型
return I_LJSON_DEFAULT;
};
///将表值插入Json11对象
void insert_value_in_json(lua_State* L, json11::Json& json_element) {
switch (lua_type(L, -1)) {
case LUA_TSTRING:
{
///字符串
const char* str = lua_tostring(L, -1);
json_element = json11::Json(str);
}
break;
case LUA_TNUMBER:
{
if (lua_isinteger(L, -1)) {
///整数
lua_Integer integer_number = lua_tointeger(L, -1);
json_element = json11::Json((int)integer_number);
} else {
///浮点数
lua_Number float_number = lua_tonumber(L, -1);
json_element = json11::Json((double)float_number);
}
}
break;
case LUA_TBOOLEAN:
{
///布尔值
bool boolean_v = (bool)lua_toboolean(L, -1);
json_element = json11::Json(boolean_v);
}
break;
case LUA_TNIL:
{
///空值
json_element = json11::Json(nullptr);
}
break;
case LUA_TUSERDATA:
case LUA_TLIGHTUSERDATA:
case LUA_TTHREAD:
case LUA_TFUNCTION:
{
///是上面的一大摞类型直接转换成相应的形式(会以字符串的形式展示)
std::string other_value;
lua_pushfstring(L, "%s:%p", lua_typename(L, lua_type(L, -1)), lua_topointer(L, -1));
other_value.append(lua_tostring(L, -1));
lua_pop(L, 1);
json_element = json11::Json(other_value);
}
break;
default:
break;
}
}
/// 将Lua表转换为Json11对象
/// !!!
/// 表的"__name"来注明表的类型:
/// "LJSON_ARRAY": 数组
/// "LJSON_OBJECT": 不可描述的对象
/// 没有"__name"键和值默认将表作为"LJSON_OBJECT"处理
/// "LJSON_OBJECT"将键统一转换为字符串
/// 因为Lua表是哈希表,元素的顺序不能确定
/// 只要是"LJSON_ARRAY"类型,那么根据表的长度迭代获取元素
void LuaTableToJson11(
lua_State* L,
json11::Json& json_object,
int tb_index
) {
///
switch (check__name_key(L, tb_index)) {
case I_LJSON_ARRAY:
{
///数组
lua_len(L, tb_index);
lua_Integer tb_for_array_len = lua_tointeger(L, -1);
lua_settop(L, tb_index);
json11::Json::array arr((const unsigned int)tb_for_array_len);
for (int i = 1; i <= tb_for_array_len; ++i) {
if (LUA_TTABLE == lua_geti(L, tb_index, i)) {
LuaTableToJson11(L, arr[i-1], lua_gettop(L));
} else {
insert_value_in_json(L, arr[i-1]);
}
///删除栈顶元素进行下一轮循环
lua_pop(L, 1);
}
json_object = arr;
}
break;
case I_LJSON_OBJECT:
{
///不可描述的对象
json11::Json::object map_json;
///起始键
lua_pushnil(L);
while (lua_next(L, tb_index)) {
///不管什么类型,转换成string类型就对了
std::string key;
switch (lua_type(L, -2)) {
case LUA_TNUMBER:
case LUA_TSTRING:
case LUA_TBOOLEAN:
{
key = lua_tostring(L, -2);
}
break;
case LUA_TTABLE:
case LUA_TTHREAD:
case LUA_TUSERDATA:
case LUA_TLIGHTUSERDATA:
case LUA_TFUNCTION:
{
lua_pushfstring(L, "%s:%p", lua_typename(L, lua_type(L, -2)), lua_topointer(L, -2));
key = lua_tostring(L, -1);
lua_pop(L, 1);
}
break;
default:
///不存在nil键
break;
}
/// 忽略__name键
if ("__name" == key){
lua_pop(L, 1);
continue;
}
if (lua_istable(L, -1)) {
map_json[key] = json11::Json();
LuaTableToJson11(L, map_json[key], lua_absindex(L, -1));
} else {
insert_value_in_json(L, map_json[key]);
}
///把值丢掉,留着键做下一次迭代
lua_pop(L, 1);
}
json_object = map_json;
}
break;
case I_LJSON_DEFAULT:
default:
{
///默认一般类型
insert_value_in_json(L, json_object);
}
break;
}
}
/// 参数1: 文件路径(字符串)
/// 参数2: 表
/// 返回值: 成功返回true, 失败返回false
/// 以覆盖的方式写入
int LJson_dump(lua_State* L) {
const char* json_save_path = luaL_checkstring(L, 1);
luaL_checktype(L, 2, LUA_TTABLE);
std::fstream fs_json(json_save_path, std::ios::out);
if (false == fs_json.is_open()) {
//luaL_error(L, "File Open|Create Error!");
lua_pushboolean(L, false);
} else {
lua_replace(L, 1);
lua_settop(L, 1);
json11::Json json_object;
LuaTableToJson11(L, json_object, 1);
std::string json_str;
json_object.dump(json_str);
///写入文件
fs_json<<json_str;
lua_pushboolean(L, fs_json.good());
fs_json.clear();
}
return 1;
}
/// 参数1: 表
/// 返回值: JSON字符串
int LJson_dumps(lua_State* L) {
///检查第一个参数是否是表
luaL_checktype(L, 1, LUA_TTABLE);
///把多余的参数丢掉
lua_settop(L, 1);
json11::Json json_object;
LuaTableToJson11(L, json_object, 1);
std::string json_str;
///导出成字符串
json_object.dump(json_str);
lua_pushstring(L, json_str.c_str());
return 1;
}
#define MAKELJSONMETHOD(name) {#name, LJson_##name}
static struct luaL_Reg LJson_method[] = {
MAKELJSONMETHOD(load), ///从文件获得JSON字符串转换为table
MAKELJSONMETHOD(loads), ///从JSON字符串转换为table
MAKELJSONMETHOD(dump), ///table导出为JSON文本文件
MAKELJSONMETHOD(dumps), ///table导出为JSON字符串
{nullptr, nullptr}
};
LJSON_EXPORT int luaopen_LJson(lua_State* L) {
luaL_newlib(L, LJson_method);
int method_table = lua_gettop(L);
//"LJSON_ARRAY"
lua_pushstring(L, LJSON_ARRAY);
lua_pushstring(L, LJSON_ARRAY);
lua_rawset(L, method_table);
//"LJSON_OBJECT"
lua_pushstring(L, LJSON_OBJECT);
lua_pushstring(L, LJSON_OBJECT);
lua_rawset(L, method_table);
return 1;
}