lua开发--字符串,json,编码转换
来源:互联网 发布:姜大声 知乎 编辑:程序博客网 时间:2024/06/06 00:41
JSON库
在进行数据传输时JSON格式目前应用广泛,因此从Lua对象与JSON字符串之间相互转换是一个非常常见的功能;目前Lua也有几个JSON库,本人用过cjson、dkjson。其中cjson的语法严格(比如unicode \u0020\u7eaf),要求符合规范否则会解析失败(如\u002),而dkjson相对宽松,当然也可以通过修改cjson的源码来完成一些特殊要求。而在使用dkjson时也没有遇到性能问题,目前使用的就是dkjson。使用时要特别注意的是大部分JSON库都仅支持UTF-8编码;因此如果你的字符编码是如GBK则需要先转换为UTF-8然后进行处理。
1.1、test_cjson.lua
local cjson = require("cjson")--lua对象到字符串local obj = { id = 1, name = "zhangsan", age = nil, is_male = false, hobby = {"film", "music", "read"}}local str = cjson.encode(obj)ngx.say(str, "<br/>")--字符串到lua对象str = '{"hobby":["film","music","read"],"is_male":false,"name":"zhangsan","id":1,"age":null}'local obj = cjson.decode(str)ngx.say(obj.age, "<br/>")ngx.say(obj.age == nil, "<br/>")ngx.say(obj.age == cjson.null, "<br/>")ngx.say(obj.hobby[1], "<br/>")--循环引用obj = { id = 1}obj.obj = obj-- Cannot serialise, excessive nesting--ngx.say(cjson.encode(obj), "<br/>")local cjson_safe = require("cjson.safe")--nilngx.say(cjson_safe.encode(obj), "<br/>")
null将会转换为cjson.null;循环引用会抛出异常Cannot serialise, excessive nesting,默认解析嵌套深度是1000,可以通过cjson.encode_max_depth()设置深度提高性能;使用cjson.safe不会抛出异常而是返回nil。
1.2、example.conf配置文件
location ~ /lua_cjson { default_type 'text/html'; lua_code_cache on; content_by_lua_file /usr/example/lua/test_cjson.lua; }
1.3、访问如http://192.168.1.2/lua_cjson将得到如下结果
{"hobby":["film","music","read"],"is_male":false,"name":"zhangsan","id":1} null false true film nil
lua-cjson文档http://www.kyne.com.au/~mark/software/lua-cjson-manual.html。
接下来学习下dkjson。
2.1、下载dkjson库
cd /usr/example/lualib/ wget http://dkolf.de/src/dkjson-lua.fsl/raw/dkjson.lua?name=16cbc26080996d9da827df42cb0844a25518eeb3 -O dkjson.lua
2.2、test_dkjson.lua
local dkjson = require("dkjson")--lua对象到字符串local obj = { id = 1, name = "zhangsan", age = nil, is_male = false, hobby = {"film", "music", "read"}}local str = dkjson.encode(obj, {indent = true})ngx.say(str, "<br/>")--字符串到lua对象str = '{"hobby":["film","music","read"],"is_male":false,"name":"zhangsan","id":1,"age":null}'local obj, pos, err = dkjson.decode(str, 1, nil)ngx.say(obj.age, "<br/>")ngx.say(obj.age == nil, "<br/>")ngx.say(obj.hobby[1], "<br/>")--循环引用obj = { id = 1}obj.obj = obj--reference cycle--ngx.say(dkjson.encode(obj), "<br/>")
默认情况下解析的json的字符会有缩排和换行,使用{indent = true}配置将把所有内容放在一行。和cjson不同的是解析json字符串中的null时会得到nil。
2.3、example.conf配置文件
location ~ /lua_dkjson { default_type 'text/html'; lua_code_cache on; content_by_lua_file /usr/example/lua/test_dkjson.lua; }
2.4、访问如http://192.168.1.2/lua_dkjson将得到如下结果
{ “hobby”:[“film”,”music”,”read”], “is_male”:false, “name”:”zhangsan”, “id”:1 }
nil
true
film
dkjson文档http://dkolf.de/src/dkjson-lua.fsl/home和http://dkolf.de/src/dkjson-lua.fsl/wiki?name=Documentation。
编码转换
我们在使用一些类库时会发现大部分库仅支持UTF-8编码,因此如果使用其他编码的话就需要进行编码转换的处理;而Linux上最常见的就是iconv,而lua-iconv就是它的一个Lua API的封装。
安装lua-iconv可以通过如下两种方式:
ubuntu下可以使用如下方式
apt-get install luarocks luarocks install lua-iconv cp /usr/local/lib/lua/5.1/iconv.so /usr/example/lualib/
源码安装方式,需要有gcc环境
下载地址:https://github.com/ittner/lua-iconv/downloads
wget https://github.com/do^Cloads/ittner/lua-iconv/lua-iconv-7.tar.gztar -xvf lua-iconv-7.tar.gzcd lua-iconv-7gcc -O2 -fPIC -I/usr/include/lua5.1 -c luaiconv.c -o luaiconv.o -I/usr/includegcc -shared -o iconv.so -L/usr/local/lib luaiconv.o -L/usr/libcp iconv.so /usr/example/lualib/
1、test_iconv.lua
ngx.say("中文")
此时文件编码必须为UTF-8,即Lua文件编码为什么里边的字符编码就是什么。
2、example.conf配置文件
location ~ /lua_iconv { default_type 'text/html'; charset gbk; lua_code_cache on; content_by_lua_file /usr/example/lua/test_iconv.lua; }
通过charset告诉浏览器我们的字符编码为gbk。
3、访问 http://192.168.1.2/lua_iconv会发现输出乱码;
此时需要我们将test_iconv.lua中的字符进行转码处理:
local iconv = require("iconv") local togbk = iconv.new("gbk", "utf-8") local str, err = togbk:iconv("中文") ngx.say(str)
通过转码我们得到最终输出的内容编码为gbk, 使用方式iconv.new(目标编码, 源编码)。
有如下可能出现的错误:
nil 没有错误成功。 iconv.ERROR_NO_MEMORY 内存不足。 iconv.ERROR_INVALID 有非法字符。 iconv.ERROR_INCOMPLETE 有不完整字符。 iconv.ERROR_FINALIZED 使用已经销毁的转换器,比如垃圾回收了。 iconv.ERROR_UNKNOWN 未知错误
另外在实际使用中进行UTF-8到GBK转换过程时,会发现有些字符在GBK编码表但是转换不了,此时可以使用更高的编码GB18030来完成转换。
更多介绍请参考http://ittner.github.io/lua-iconv/。
位运算
Lua 5.3之前是没有提供位运算支持的,需要使用第三方库,比如LuaJIT提供了bit库。
1、test_bit.lua
local bit = require("bit") ngx.say(bit.lshift(1, 2))
lshift进行左移位运算,即得到4。
其他位操作API请参考http://bitop.luajit.org/api.html。Lua 5.3的位运算操作符http://cloudwu.github.io/lua53doc/manual.html#3.4.2.
cache
ngx_lua模块本身提供了全局共享内存ngx.shared.DICT可以实现全局共享,另外可以使用如Redis来实现缓存。另外还一个lua-resty-lrucache实现,其和ngx.shared.DICT不一样的是它是每Worker进程共享,即每个Worker进行会有一份缓存,而且经过实际使用发现其性能不如ngx.shared.DICT。但是其好处就是不需要进行全局配置。
1、创建缓存模块来实现只初始化一次:
vim /usr/example/lualib/mycache.lua
local lrucache = require("resty.lrucache")--创建缓存实例,并指定最多缓存多少条目local cache, err = lrucache.new(200)if not cache then ngx.log(ngx.ERR, "create cache error : ", err)endlocal function set(key, value, ttlInSeconds) cache:set(key, value, ttlInSeconds)endlocal function get(key) return cache:get(key)endlocal _M = { set = set, get = get}return _M
此处利用了模块的特性实现了每个Worker进行只初始化一次cache实例。
2、test_lrucache.lua
local mycache = require("mycache") local count = mycache.get("count") or 0 count = count + 1 mycache.set("count", count, 10 * 60 * 60) --10分钟 ngx.say(mycache.get("count"))
可以实现诸如访问量统计,但仅是每Worker进程的。
3、example.conf配置文件
location ~ /lua_lrucache { default_type 'text/html'; lua_code_cache on; content_by_lua_file /usr/example/lua/test_lrucache.lua; }
访问如http://192.168.1.2/lua_lrucache测试。
更多介绍请参考https://github.com/openresty/lua-resty-lrucache。
字符串处理
Lua 5.3之前没有提供字符操作相关的函数,如字符串截取、替换等都是字节为单位操作;在实际使用时尤其包含中文的场景下显然不能满足需求;即使Lua 5.3也仅提供了基本的UTF-8操作。
Lua UTF-8库
https://github.com/starwing/luautf8
LuaRocks安装
#首先确保git安装了 apt-get install git luarocks install utf8 cp /usr/local/lib/lua/5.1/utf8.so /usr/example/lualib/
源码安装
wget https://github.com/starwing/luautf8/archive/master.zipunzip master.zipcd luautf8-master/gcc -O2 -fPIC -I/usr/include/lua5.1 -c utf8.c -o utf8.o -I/usr/includegcc -shared -o utf8.so -L/usr/local/lib utf8.o -L/usr/lib
1、test_utf8.lua
local utf8 = require("utf8") local str = "abc中文" ngx.say("len : ", utf8.len(str), "<br/>") ngx.say("sub : ", utf8.sub(str, 1, 4))
文件编码必须为UTF8,此处我们实现了最常用的字符串长度计算和字符串截取。
2、example.conf配置文件
location ~ /lua_utf8 { default_type 'text/html'; lua_code_cache on; content_by_lua_file /usr/example/lua/test_utf8.lua; }
3、访问如http://192.168.1.2/lua_utf8测试得到如下结果
len : 5
sub : abc中
字符串转换为unicode编码:
local bit = require("bit")local bit_band = bit.bandlocal bit_bor = bit.borlocal bit_lshift = bit.lshiftlocal string_format = string.formatlocal string_byte = string.bytelocal table_concat = table.concatlocal function utf8_to_unicode(str) if not str or str == "" or str == ngx.null then return nil end local res, seq, val = {}, 0, nil for i = 1, #str do local c = string_byte(str, i) if seq == 0 then if val then res[#res + 1] = string_format("%04x", val) end seq = c < 0x80 and 1 or c < 0xE0 and 2 or c < 0xF0 and 3 or c < 0xF8 and 4 or --c < 0xFC and 5 or c < 0xFE and 6 or 0 if seq == 0 then ngx.log(ngx.ERR, 'invalid UTF-8 character sequence' .. ",,," .. tostring(str)) return str end val = bit_band(c, 2 ^ (8 - seq) - 1) else val = bit_bor(bit_lshift(val, 6), bit_band(c, 0x3F)) end seq = seq - 1 end if val then res[#res + 1] = string_format("%04x", val) end if #res == 0 then return str end return "\\u" .. table_concat(res, "\\u")endngx.say("utf8 to unicode : ", utf8_to_unicode("abc中文"), "<br/>")
如上方法将输出utf8 to unicode : \u0061\u0062\u0063\u4e2d\u6587。
到此基本的字符串操作就完成了,其他luautf8模块的API和LuaAPI类似可以参考
http://cloudwu.github.io/lua53doc/manual.html#6.4
http://cloudwu.github.io/lua53doc/manual.html#6.5
另外对于GBK的操作,可以先转换为UTF-8,最后再转换为GBK即可。
- lua开发--字符串,json,编码转换
- 第五章 常用Lua开发库2-JSON库、编码转换、字符串处理
- Lua与json字符串转换之UTF8
- lua utf8 gbk 编码转换
- JSON: Python Objects与String之间转换【json.dumps把python任意数据类型转换成字符串,json.loads把字符串转换为unicode编码】
- java字符串编码转换
- 字符串常用编码转换
- java字符串编码转换
- wxString字符串编码转换
- 字符串编码转换
- 字符串编码转换
- java 字符串编码转换
- PHP转换字符串编码
- NSString字符串编码转换
- php字符串编码转换
- java字符串编码转换
- 字符串编码转换
- 字符串编码转换
- 使用python和IBM speech to text 进行 语音识别
- windows8系统 出现不能关机和重启 但是能够休眠的问题
- 【LEETCODE】236-Lowest Common Ancestor of a Binary Tree
- JS 实现瀑布流
- 将 vlfeat 编译成静态库
- lua开发--字符串,json,编码转换
- 【leetcode】Maximum Subarray
- eclipse连接access结果集自动关闭报错
- 为Hexo博客文章添加关键字
- Android——布局layout中的一些属性
- ZABBIX监控MYSQL
- 日期处理
- git 撤销commit中单个文件的修改
- 对谷歌浏览器滚动条进行样式设置