在Redis的lua脚本编写中,我们可能会用到json的序列化和反序列化。
Json序列化:
-- RedisLuaCjsonEncode.lua文件
local userName = ARGV[1];
local userObject = {
name = userName,
age = 14,
address = 'China'
}
local userJson = cjson.encode(userObject);
if redis.call('set', KEYS[1], userJson) == 0
then
return -1
else
return userJson
end
Json反序列化:
-- RedisLuaCjsonDecode.lua文件
local userInfo = redis.call('get', KEYS[1])
local userJson = cjson.decode(userInfo)
return userJson.name;
上面这两段代码是笔者写出的两个Json序列化和反序列化的小例子,相信看过前两篇文章的读者都能读懂什么意思。有兴趣的话,可以自行执行以下命令看一下效果:
## 运行RedisLuaCjsonEncode.lua文件,向redis中插入一条序列化成json格式的字符串
[root@vm01 learn_lua]# redis-cli -a 123456 --eval RedisLuaCjsonEncode.lua userInfo , zhangsan
## 运行RedisLuaCjsonDecode.lua文件,从redis中一条json格式的字符串,并将其反序列化,并取出其中的name字段的值。
[root@vm01 learn_lua]# redis-cli -a 123456 --eval RedisLuaCjsonDecode.lua userInfo
但如果有兴趣在读者想编写一段和Redis无关的使用 cjson 的纯 Lua 脚本,想要运行,会发现:我跳!运行不了。会报以下错误:
[root@vm01 lua_cjson]# lua cjson_demo.lua
lua: cjson_demo.lua:1: module 'cjson' not found:
no field package.preload['cjson']
no file './cjson.lua'
no file '/usr/share/lua/5.1/cjson.lua'
no file '/usr/share/lua/5.1/cjson/init.lua'
no file '/usr/lib64/lua/5.1/cjson.lua'
no file '/usr/lib64/lua/5.1/cjson/init.lua'
no file './cjson.so'
no file '/usr/lib64/lua/5.1/cjson.so'
no file '/usr/lib64/lua/5.1/loadall.so'
stack traceback:
[C]: in function 'require'
cjson_demo.lua:1: in main chunk
[C]: ?
问题原因: lua-cjson 是一个简单小巧的开源动态库,可被 Lua 脚本 require 加载在 Lua 中通过一系列的 lua-cjson API 调用完成 Lua 值与 Json 值的相互转换(编码及解码)。 即:原生 Lua 并不支持 lua-cjson,需要我们手动将cjson编译到 Lua 环境方可使用。
Redis中使用cjson 的 lua脚本可以直接执行,而不报错。实际是Redis客户端将脚本传输到了Redis服务端,后期 Lua 的脚本都在服务端运行。而Redis服务端,已经在Redis编译安装的过程中,将 cjson开源库以及Lua环境 都已编译进去 不信,您在Redis服务端看:
## 看查询结果的后两行
[root@vm01 lua_cjson]# sudo find / -name lua
/usr/bin/lua
/usr/lib64/lua
/usr/local/lib/lua
/usr/local/share/lua
/usr/local/lua-cjson-2.1.0/lua
/usr/share/lua
/usr/share/locale/lua
/opt/soft/redis/redis-5.0.5/deps/lua
/opt/soft/redis/redis-5.0.5/deps/lua/src/lua
那就想办法安装 lua-cjson 呗。在网上找了很多 lua-cjson 的安装方案,发现直接安装,在make编译时总会报错,就是 lua.h
和 lauxlib.h
两个文件找不到。
[root@vm01 lua-cjson-2.1.0]# make
cc -c -O3 -Wall -pedantic -DNDEBUG -I/usr/local/include/luajit-2.0/include -fpic -o lua_cjson.o lua_cjson.c
lua_cjson.c:43:17: error: lua.h: No such file or directory
lua_cjson.c:44:21: error: lauxlib.h: No such file or directory
其实是因为 lua-cjson 还要依赖 lua 环境。我们需要安装 LuaJit
这么一个Lua代码解析器,后面可以使用luajit命令执行 cjson 的脚本。
安装步骤:
## step1. 解压 LuaJIT-2.0.5.zip 到 /usr/local/ 目录
[root@vm11 ~]# unzip LuaJIT-2.0.5.zip -d /usr/local/
[root@vm11 ~]# cd /usr/local/LuaJIT-2.0.5/
[root@vm11 LuaJIT-2.0.5]# pwd
/usr/local/LuaJIT-2.0.5
## step2. 在/usr/local/LuaJIT-2.0.5/目录下执行 make && make install 命令
## 看到最后一行成功安装即可
[root@vm11 LuaJIT-2.0.5]# make && make install
==== Building LuaJIT 2.0.5 ====
make -C src
make[1]: Entering directory `/usr/local/LuaJIT-2.0.5/src'
make[1]: Nothing to be done for `default'.
make[1]: Leaving directory `/usr/local/LuaJIT-2.0.5/src'
==== Successfully built LuaJIT 2.0.5 ====
==== Installing LuaJIT 2.0.5 to /usr/local ====
mkdir -p /usr/local/bin /usr/local/lib /usr/local/include/luajit-2.0 /usr/local/share/man/man1 /usr/local/lib/pkgconfig /usr/local/share/luajit-2.0.5/jit /usr/local/share/lua/5.1 /usr/local/lib/lua/5.1
cd src && install -m 0755 luajit /usr/local/bin/luajit-2.0.5
cd src && test -f libluajit.a && install -m 0644 libluajit.a /usr/local/lib/libluajit-5.1.a || :
rm -f /usr/local/bin/luajit /usr/local/lib/libluajit-5.1.so.2.0.5 /usr/local/lib/libluajit-5.1.so /usr/local/lib/libluajit-5.1.so.2
cd src && test -f libluajit.so && \
install -m 0755 libluajit.so /usr/local/lib/libluajit-5.1.so.2.0.5 && \
ldconfig -n /usr/local/lib && \
ln -sf libluajit-5.1.so.2.0.5 /usr/local/lib/libluajit-5.1.so && \
ln -sf libluajit-5.1.so.2.0.5 /usr/local/lib/libluajit-5.1.so.2 || :
cd etc && install -m 0644 luajit.1 /usr/local/share/man/man1
cd etc && sed -e "s|^prefix=.*|prefix=/usr/local|" -e "s|^multilib=.*|multilib=lib|" luajit.pc > luajit.pc.tmp && \
install -m 0644 luajit.pc.tmp /usr/local/lib/pkgconfig/luajit.pc && \
rm -f luajit.pc.tmp
cd src && install -m 0644 lua.h lualib.h lauxlib.h luaconf.h lua.hpp luajit.h /usr/local/include/luajit-2.0
cd src/jit && install -m 0644 bc.lua v.lua dump.lua dis_x86.lua dis_x64.lua dis_arm.lua dis_ppc.lua dis_mips.lua dis_mipsel.lua bcsave.lua vmdef.lua /usr/local/share/luajit-2.0.5/jit
ln -sf luajit-2.0.5 /usr/local/bin/luajit
==== Successfully installed LuaJIT 2.0.5 to /usr/local ====
[root@vm11 ~]# tar -xzf lua-cjson-2.1.0.tar.gz -C /usr/local/
[root@vm11 ~]# cd /usr/local/lua-cjson-2.1.0
[root@vm11 lua-cjson-2.1.0]# pwd
/usr/local/lua-cjson-2.1.0
步骤2:修改 /usr/local/lua-cjson-2.1.0/Makefile
文件
将 LUA_INCLUDE_DIR = $(PREFIX)/include
修改为:LUA_INCLUDE_DIR = /usr/local/include/luajit-2.0
步骤3:执行 make && make install
命令,看到如下提示,则证明安装成功
[root@vm11 lua-cjson-2.1.0]# make && make install
cc -c -O3 -Wall -pedantic -DNDEBUG -I/usr/local/include/luajit-2.0 -fpic -o lua_cjson.o lua_cjson.c
cc -c -O3 -Wall -pedantic -DNDEBUG -I/usr/local/include/luajit-2.0 -fpic -o strbuf.o strbuf.c
cc -c -O3 -Wall -pedantic -DNDEBUG -I/usr/local/include/luajit-2.0 -fpic -o fpconv.o fpconv.c
cc -shared -o cjson.so lua_cjson.o strbuf.o fpconv.o
mkdir -p //usr/local/lib/lua/5.1
cp cjson.so //usr/local/lib/lua/5.1
chmod 755 //usr/local/lib/lua/5.1/cjson.so
luajit
命令执行相关lua脚本[root@vm11 ~]# luajit cjson_demo.lua
true
[1,2,3,4,5,6]
6.66
"I am test1280"
{"addr":"BeiJing","tel":"1569989xxxx","age":24,"name":"Jiang","email":"[email protected]"}
cjson_demo.lua脚本如下:
local cjson = require "cjson"
-- 创建实例
local cjson2 = cjson.new()
-- 布尔类型
local lua_bool = true
print(cjson2.encode(lua_bool))
-- 数组类型
local lua_array = {1, 2, 3, 4, 5, 6}
print(cjson2.encode(lua_array))
-- 数值类型
local lua_number = 6.66
print(cjson2.encode(lua_number))
-- 字符串类型
local lua_string = "I am test1280"
print(cjson2.encode(lua_string))
-- 对象类型
local lua_object = {
["name"] = "Jiang",
["age"] = 24,
["addr"] = "BeiJing",
["email"] = "[email protected]",
["tel"] = "1569989xxxx"
}
print(cjson2.encode(lua_object))