A. 纯lua判断字符串是否是规范的json格式
楼主参考这个:网页链接
最近发现解码json串时,如果json串本身格式错误会造成程序报错,那当然不能忍,于是断断续续抽着间隙来写写了一个礼拜终于写了一个较为完整的纯lua脚本来判断json串。
因为json用的不是很多,刚开始只是了解到这样的格式: {“a”:“1”,“b”:“2”,“c”:"3"},还有复杂一点的这种:{"links": [
{ "a": "1", "b": "2" },
{"c": "3","d": "4"
}]},对于这种,一开始我想的处理方式是先找[..] 然后截取出来,再找{...}然后找逗号",",截取逗号前部分后后部分,利用到string.gsub判断这一小段是不是 "a":"1"这样的格式,源码如下,后面还有处理无限嵌套json的源码:
--判断是否是json
function ifIsJson(jsonString)
local head
local pos1,pos2
jsonString =jsonString:atrim()
local String1=string.sub(jsonString,1,1) --最外部大括号
local String2 = string.sub(jsonString,#jsonString)
if String1=="{" and String2 =="}" then
String1=jsonString
jsonString=string.sub(jsonString,2,-2) --去掉最外部括号
pos1,_=string.find(jsonString,"%[")
if pos1 then
pos2,_ = string.find(jsonString,"%]")
if pos2 then
head=string.sub(jsonString,2,pos1-1)
local a,b=string.gsub(head,"("-)(.-)("-):","")
if a =="" and b==1 then
head=string.sub(jsonString,pos1+1,pos2-1)
while true do
if (pos2)==#jsonString then --没有后续的了
local result= ContinueCheck(head) --传入 []里的内容
if result then return true else return false end
else --还有
local result= ContinueCheck(head) --传入 []里的内容
if result== false then return false end
jsonString=string.sub(jsonString,pos2+1,#jsonString) --记录下后面部分
pos1,_=string.find(jsonString,"%[")
if pos1 then
pos2,_ = string.find(jsonString,"%]")
if pos2 then
head=string.sub(jsonString,2,pos1-1)
local a,b=string.gsub(head,"("-)(.-)("-):","")
if a ~="" and b~=1 then return false end -- "head":[{....},{.....},{.....}] 其中的head格式不正确
head=string.sub(jsonString,pos1+1,pos2-1) --下一次循环传入的参数
else
return false--缺少]
end
else
return false --[]缺少[]
end
end
end
else
return false -- "head":[{....},{.....},{.....}] 其中的head格式不正确
end
else
return false --不匹配[]
end
else --没有中括号,简单的单个{}json处理
local result =ContinueCheck(String1)
if result then return true else return false end
end
else
return false --不匹配{}
end
end
function ContinueCheck(jsonString)
local stringLength=#jsonString
local pos1,pos2=0,0
local JsonTable={}
local i=1
while (true) do --截取{....}并且存入表JsonTable中
pos1,_=string.find(jsonString,"{",pos1+1)
if pos1 then
pos2,_=string.find(jsonString,"}",pos2+1)
if pos2 then
JsonTable[i]=string.sub(jsonString,pos1+1,pos2-1)
else
return false
end
else
return false
end
if pos2==#jsonString then break end
i=i+1
end
local a,b
local j=1
while (true) do
jsonString=JsonTable[j] --一个一个值检查
while (true) do
local q,_=string.find(jsonString,",")
if q~= nil then --"a":"i","b":"j"找这之间的逗号
local jsonString2=string.sub(jsonString,1,q-1) --,号前
jsonString=string.sub(jsonString,q+1,#jsonString) --,号后
a,b=string.gsub(jsonString2,"("-)(.-)("-):","")
else --没有则为key:value 的最后一个
a,b=string.gsub(jsonString,"("-)(.-)("-):","")
end
if b==1 then
a,b=string.gsub(a,"("-)(.+)("+)","")
if a=="" then
mSleep(10)
else
a=tonumber(a)
if type(a) == "number" then
mSleep(10)
else
return false
end
end
else
return false
end
if q == nil then --找到最后啦
break
end
end
if j==i then return true end
j=j+1
end
end
其中msleep只是封装的等待,可以看出这样写的会嵌套超多层,也就我这种格式规范对的整整齐齐的才看得清,不过勉强作为上述简单的json判断还是没问题的,但是后来考虑到如果json有嵌套,一直嵌套[..]和{..}那要怎么办呢,明显这种从{..}中从前到后截取判断的方法是不实用的,然后又花了几天写了一个可以判断任意嵌套的封装函数,有点长还没做优化但是已经可以正常使用了,代码如下:
function ifIsJson(JsonString)
local pos1,pos2,pos3,pos4=0,0,0,0
local counter1,counter2,counter3,counter4=0,0,0,0
local string1,string2
local Mytable,Mytable2={},{}
local i,j=1,1
JsonString=JsonString:atrim()
string1=string.sub(JsonString,1,1)
string2=string.sub(JsonString,-1,-1)
if string1=="{" and string2=="}" then --查看各种括号是否成对存在
_,pos1=string.gsub(JsonString,"{","{")
_,pos2=string.gsub(JsonString,"}","}")
_,pos3=string.gsub(JsonString,"%[","[")
_,pos4=string.gsub(JsonString,"%]","]")
if pos1~=pos2 or pos3~=pos4 then return false end
else return false end
while (true) do
pos1,pos2=string.find(JsonString,",%[{",pos1)-- 找 ,[{ 找到后找 }]
if pos1 then
pos3,pos4=string.find(JsonString,"}]",pos4)
if pos3 then
string1=string.sub(JsonString,pos1,pos4)
_,counter1=string.gsub(string1,"{","{") --查看各种括号是否成对存在
_,counter2=string.gsub(string1,"}","}")
_,counter3=string.gsub(string1,"%[","[")
_,counter4=string.gsub(string1,"%]","]")
if counter1 == counter2 and counter3== counter4 then
Mytable[i]=string.sub(JsonString,pos2,pos3) --{....}
i=i+1
string1=string.sub(JsonString,1,pos1-1)
string2=string.sub(JsonString,pos4+1)
JsonString=string1..string2 -- 去掉,{[..}]
pos4=pos1
end
else return false end
else
pos1,pos2,pos3,pos4=1,1,1,1
pos1,pos2=string.find(JsonString,"%[{") --找[{ 找到后找 }]没有则跳出
if pos1 then
pos3,pos4=string.find(JsonString,"}]")
if pos3 then
string1=string.sub(JsonString,pos1,pos4)
_,counter1=string.gsub(string1,"{","{") --查看各种括号是否成对存在
_,counter2=string.gsub(string1,"}","}")
_,counter3=string.gsub(string1,"%[","[")
_,counter4=string.gsub(string1,"%]","]")
if counter1 == counter2 and counter3== counter4 then
Mytable[i]=string.sub(JsonString,pos2,pos3) --{....}
i=i+1
string1=string.sub(JsonString,1,pos1-1)
string2=string.sub(JsonString,pos4+1)
JsonString=string1..""""..string2 -- 去掉,[{..}]
pos4=pos1
end
else return false end
else break end
end
end
i=i-1
if Mytable[i]~= nil then
pos1,pos2,pos3,pos4=1,1,1,1
while (true) do --截取嵌套n层的最里面的[{.....}]
repeat -- 找table[]中[{最靠后的这符号,
pos1,pos2=string.find(Mytable[i],"%[{",pos2)
if pos1 then pos3,pos4=pos1,pos2 end
until pos1==nil
pos1,pos2=string.find(Mytable[i],"}]",pos4) --找串中pos4之后}]最靠前的这个符号
if pos1 then
Mytable2[j]=string.sub(Mytable[i],pos4,pos1) --[ {....} ]
j=j+1
string1=string.sub(Mytable[i],1,pos3-1)
stirng2=string.sub(Mytable[i],pos2+1)
Mytable[i]=string1..""""..string2
else
Mytable2[j]=Mytable[i]
j=j+1
i=i-1
if i== 0 then break end--直到找不到成对的[{}]
end
pos2=1
end
end
Mytable2[j]=JsonString
i=1
Mytable={}
pos1,pos2,pos3,pos4=0,0,1,1
while (true) do
repeat
pos1,_=string.find(Mytable2[j],"{",pos2+1)
if pos1 then pos2=pos1 end
until pos1 == nil
pos3,_=string.find(Mytable2[j],"}",pos2)
if pos3 and pos2~=1 then
Mytable[i]=string.sub(Mytable2[j],pos2,pos3) -- {...}
i=i+1
string1=string.sub(Mytable2[j],1,pos2-1)
string2=string.sub(Mytable2[j],pos3+1)
Mytable2[j]=string1..""""..string2
else
Mytable[i]=string.sub(Mytable2[j],1,pos3)
i=i+1
j=j-1
if j==0 then break end
end
pos2=0
-- 串b截取 { "id":"243125b4-5cf9-4ad9-827b-37698f6b98f0" } 这样的格式 存进table[j]
-- 剩下一个 "image":{ "id":"243125b4-5cf9-4ad9-827b-37698f6b98f0","a":"e0", "d":"2431-f6b98f0","f":"243125b98f0"--}这样的也存进table[j+1]
end
i=i-1
for n=1,i do --去除{}
Mytable[n]=string.sub(Mytable[n],2,-2)
end
while (true) do
pos1,_=string.find(Mytable[i],",")
if pos1~= nil then --"a":"i","b":"j"找这之间的逗号
string1=string.sub(Mytable[i],1,pos1-1)--,前
Mytable[i]=string.sub(Mytable[i],pos1+1)
pos2,_=string.find(string1,""")
if pos2==1 then
pos3,pos4=string.find(string1,"":",2)
if pos3 then
string2=string.sub(string1,pos4+1)
else
--("发现错误1", 1)
return false
end
else
--("发现错误2", 1)
return false
end
else
pos2,_=string.find(Mytable[i],""")
if pos2==1 then
pos3,pos4=string.find(Mytable[i],"":",2)
if pos3 then
string2=string.sub(Mytable[i],pos4+1)
else
--("发现错误3", 1)
return false
end
else
--("发现错误4", 1)
return false
end
end
pos2,pos3=string.gsub(string2,"("-)(.+)("+)","")
if pos2=="" or pos2 == "null" then
--("这一个串格式正确", 2)
else
pos2=tonumber(pos2)
if type(pos2) == "number" then
--("这一个串格式正确2", 2)
else
--("发现错误5", 1)
return false
end
end
if pos1== nil then
i=i-1
if i==0 then return true end
end
end
end
这里有一个很核心的思想是既然是无限嵌套都要判断的出来,那么脚本要做到的是获取到最最里面的{..}单层结构的json,博猪是通过找最后的[ 和{ ,然后在此位置之后找最靠近的]和},截取出来后依然是按逗号截取出最小部分"a":"1"来判断格式,如果对你有帮助的话记得点赞哦
B. lua接收到的结构体,如何传给C/C++,并解析成json字符串
一、从字符串中读取JSON
#include
#include "json/json.h"
using namespace std;
int main()
{
//字符串
const char * str =
"{\"praenomen\":\"Gaius\",\"nomen\":\"Julius\",\"cognomen\":\"Caezar\","
"\"born\":-100,\"died\":-44}" ;
Json::Reader reader;
Json::Value root;
//从字符串中读取数据
if (reader.parse(str,root))
{
string praenomen = root[ "praenomen" ].asString();
string nomen = root[ "nomen" ].asString();
string cognomen = root[ "cognomen" ].asString();
int born = root[ "born" ].asInt();
int died = root[ "died" ].asInt();
cout << praenomen + " " + nomen + " " + cognomen
<< " was born in year " << born
<< ", died in year " << died << endl;
}
return 0;
}
makefile文件
LIB=-L /usr/local/lib/libjson/ -ljson_linux- gcc -4.4.7_libmt
a: a.o
g++ -o a -std=c++0x a.o $(LIB)
a.o: a.cpp
g++ -c a.cpp
clean:
rm -rf a.o a
二、从文件中读取JSON
PersonalInfo.json(一个存储了JSON格式字符串的文件)
{
"name" : "Tsybius" ,
"age" :23,
"sex_is_male" : true ,
"partner" :
{
"partner_name" : "Galatea" ,
"partner_age" :21,
"partner_sex_is_male" : false
},
"achievement" :[ "ach1" , "ach2" , "ach3" ]
}
#include
#include
#include "json/json.h"
using namespace std;
int main()
{
Json::Reader reader;
Json::Value root;
//从文件中读取
ifstream is;
is.open( "PersonalInfo.json" , ios::binary);
if (reader.parse(is,root))
{
//读取根节点信息
string name = root[ "name" ].asString();
int age = root[ "age" ].asInt();
bool sex_is_male = root[ "sex_is_male" ].asBool();
cout << "My name is " << name << endl;
cout << "I'm " << age << " years old" << endl;
cout << "I'm a " << (sex_is_male ? "man" : "woman" ) << endl;
//读取子节点信息
string partner_name = root[ "partner" ][ "partner_name"].asString();
int partner_age = root[ "partner" ][ "partner_age" ].asInt();
bool partner_sex_is_male = root[ "partner" ]["partner_sex_is_male" ].asBool();
cout << "My partner's name is " << partner_name << endl;
cout << (partner_sex_is_male ? "he" : "she" ) << " is "
<< partner_age << " years old" << endl;
//读取数组信息
cout << "Here's my achievements:" << endl;
for ( int i = 0; i < root[ "achievement" ].size(); i++)
{
string ach = root[ "achievement" ][i].asString();
cout << ach << '\t' ;
}
cout << endl;
cout << "Reading Complete!" << endl;
}
is.close();
return 0;
}
makefile
?
LIB=-L /usr/local/lib/libjson/ -ljson_linux- gcc -4.4.7_libmt
a: a.o
g++ -o a -std=c++0x a.o $(LIB)
a.o: a.cpp
g++ -c a.cpp
clean:
rm -rf a.o a
三、将信息保存为JSON格式
a.cpp
#include
#include
#include "json/json.h"
using namespace std;
int main()
{
//根节点
Json::Value root;
//根节点属性
root[ "name" ] = Json::Value( "Tsybius" );
root[ "age" ] = Json::Value(23);
root[ "sex_is_male" ] = Json::Value( true );
//子节点
Json::Value partner;
//子节点属性
partner[ "partner_name" ] = Json::Value( "Galatea" );
partner[ "partner_age" ] = Json::Value(21);
partner[ "partner_sex_is_male" ] = Json::Value( false );
//子节点挂到根节点上
root[ "partner" ] = Json::Value(partner);
//数组形式
root[ "achievement" ].append( "ach1" );
root[ "achievement" ].append( "ach2" );
root[ "achievement" ].append( "ach3" );
//直接输出
cout << "FastWriter:" << endl;
Json::FastWriter fw;
cout << fw.write(root) << endl << endl;
//缩进输出
cout << "StyledWriter:" << endl;
Json::StyledWriter sw;
cout << sw.write(root) << endl << endl;
//输出到文件
ofstream os;
os.open( "PersonalInfo" );
os << sw.write(root);
os.close();
return 0;
}
makefile
LIB=-L /usr/local/lib/libjson/ -ljson_linux- gcc -4.4.7_libmt
a: a.o
g++ -o a -std=c++0x a.o $(LIB)
a.o: a.cpp
g++ -c a.cpp
clean:
rm -rf a.o a
{
"achievement" : [ "ach1" , "ach2" , "ach3" ],
"age" : 23,
"name" : "Tsybius" ,
"partner" : {
"partner_age" : 21,
"partner_name" : "Galatea" ,
"partner_sex_is_male" : false
},
"sex_is_male" : true
}
C. lua里怎样把一段字符串转换成json
你可以搜索一下luajson
有2个版本的 一个是纯lua版 一个是C版
前者适用性更广 适合任何平台 但是毕竟效率回比较低答
C版运算速度更快 但是你得会根据你的不同平台来发布编译不同的dll/so/... 来适应你的platform
链接我就不能给了 不然答案会被吞掉 自己搜一下吧
D. lua序列化与反序列化
主要用于存储对象状态为另一种通用格式,比如存储为二进制、xml、json等等,把对象转换成这种格式就叫序列化,而反序列化通常是从这种格式转换回来。
使用序列化主要是因为跨和对象存储的需求,因为网络上只允许字符串或者二进制格式,而文件需要使用二进制流格式,如果想把一个内存中的对象存储下来就必须使用序列化转换为xml(字符串)、json(字符串)或二进制(流)
E. 用lua语言访问一个URL,然后获取到相应的json数据
local cjson = require("cjson");
local file = io.open(path,"r")
local json = file:read("*a")
file:close()
youWantJson = cjson.decode(json)
F. 我的MAC编译LUA-CJSON模块时报如下错误,求大神解答~~!
把Makefile里的 CJSON_LDFLAGS = -shared改成CJSON_LDFLAGS = -bundle -undefined dynamic_lookup试试看
G. 【Lua】cjson解析null
最近遇到一个问题,在lua中使用cjson解析json中数据为null时,解析出来是一个userdata。如图:
我们需要判断这个值使用cjson.null。
具体的可以看看 文档 很详细。
H. JSON的作用
JavaScript 三种创建对象的方法 JavaScript中对象的创建有以下几种方式: (1)使用内置对象 (2)使用JSON符号 (3)自定义对象构造 一、使用内置对象JavaScript可用的内置对象可分为两种: 1,JavaScript语言原生对象(语言级对象),如String、Object、Function等; 2,JavaScript运行期的宿主对象(环境宿主级对象),如window、document、body等。 我们所说的使用内置对象,是指通过JavaScript语言原生对象的构造方法,实例化出一个新的对象。如: 代码如下:var str = new String("实例初始化String"); var str1 = "直接赋值的String"; var func = new Function("x","alert(x)");//示例初始化func var o = new Object();//示例初始化一个Object二、使用JSON符号 (i)何谓JSON ? JSON (JavaScript Object Notation)即JavaScript对象命名,是一种轻量级的数据交换格式,易于阅读和编写,同时也易于及其解析和生成。它基于《JavaScript Programming Language, Standard ECMA-262 3rd Edition - December 1999》的一个子集。JSON是完全独立于语言的文本格式,因此成为数据交换的理想格式。 JSON作为JavaScript的一个自己,同时ActionScript、C、C#、ColdFusion、E、Java、JavaScript、ML、ObjectiveCAML、Perl、PHP、Python、Rebol、Ruby、Lua等一系列的语言都提供支持,使得JSON成为Ajax开发的首选方案。 JSON有两种构建方式,一种是采用简单的“键/值对”的集合,在不同的语言中被理解为对象、记录、结构、字典、哈希表、有键列表,或者关联数组等,另一种采用有序的值列表,大部分语言把它理解为数组。 常用的创建方式是第一种,即采用“键/值对”集合的形式。在这种形式下,一个对象以“”(右括号)结束。每个“名称”后跟一个“:”(冒号),“ ‘键/值' 对”之间使用“,”(逗号)分隔。 JSON具有以下特点:(1)简单格式化的数据交换;(2)易于人们的读写习惯;(3)易于机器的分析和运行。 在JavaScript中,JSON被理解为对象。通过字符串形式的JSON,数据可以很方便地解析成JavaScript独享,并进行数据的读取传递。通过JSON,在一定程度上客服了JavaScript对象无法作为参数系列化传递的问题。 1,简单的JSON 2,JSON值的类型 JSON的值可以是简单的数据类型,例如数字、浮点、字符等,也可以是数组及对象。例如以数组作为member键值的JSON: ,,,]} ,,,], author:[,,}] } 3,在JavaScript中使用JSON JSON是JavaScript原生格式,这意味着在JavaScript中处理JSON数据不需要任何特殊的API或者工具包,JavaScript默认将JSON当做一个对象处理。 将对象传递给一个变量,例如: 代码如下:var somebooks = ,,,], author:[,,}] }JSON的每个“键”相当于对象的属性,例如访问book中的第一个条目,在JavaScript中,就可以简单地使用“somebooks.book[0].name”来获取“三国演义”这个值。 我们不但可以将一个JSON字符串转化为对象,反过来将一个对象“编译”为一个JSON字符串,以方便JavaScript中的对象的传输。例如: 代码如下:var Animals = new Object(); Animals.name = "dog"; Animals.sex = "Male"; Animals.age = "2";Animals对象无法被序列化传输,将Animals对象转化为JSON字符串,也就是“”。这样,把该JSON字符串作为HTTP请求的一个参数传递,从而达到序列化传输Animals对象的目的。 (ii
如果帮助到您,请记得采纳为满意答案哈,谢谢!祝您生活愉快! vae.la
I. lua绑定序列号
通过genbindings.py绑定。
通常需要序列化一些数据,也就是将数据转换为一个字节流或字符流,然后就可以将其方便的持久化。文本序列化可选择的格式非常多:SOAP、Json甚至自定义xml等,不过lua脚本也是一个不错的选择方案。写好了c++代码之后,我们需要做的,便是生成桥接文件,对于桥接文件的生成,使用的tolua的工具。
J. 使用lua-cmsgpack序列化和反序列化lua对象
lua-cmsgpack是一个开源的MessagePack实现方式、纯C的库,没有任何其它依赖,编译后可以直接被lua调用,目前主要支持Lua 5.1/5.2/5.3 版本。
1、什么是MessagePack?
官方的解释是:
跟JSON及其类似,但是比JSON更快并且占用空间更小,举个官方给出的例子,直接截官方图:
翻译官方的解释:
MessagePack是一种高效的二进制序列化格式, 它允许在多种语言(如JSON)之间交换数据,但它越来越小, 小整数被编码为单个字节,典型的短字符串除了字符串本身之外还需要一个额外的字节。
目前市面上流行的开发语言MessagePack几乎支持,官方的地址为: http://msgpack.org/Lua MessagePack也提供了一套开源库,地址在: https://github.com/fperrad/lua-MessagePack/ 。
但是,作者使用的是lua-cmsgpack,至于哪个比较优异,作者还没有去比较,主要是先发现了lua-cmsgpack,后面看了下README文件,使用方法应该是差不多的,大家可以拿来参考。
lua-cmsgpack包括官方提供的lua-MessagePack都需要自行编译,因为可能平台太多,所以官方没有为每一个平台提供编译好的版本。lua-cmsgpack的github地址为: https://github.com/antirez/lua-cmsgpack
git clone下来之后需要安装cmake工具,mac平台直接在项目目录:
即可,当然需要预先安装lua,并且是5.1版本以上的。
主要说下CentOS平台下cmake可能会出现的问题,如果cmake的过程出现以下错误:
出现以上错误的话,需要自行安装lua的一些依赖库,一般:
就可以了,如果还不行,再试试下面的命令:
编译完成之后会生成cmsgpack.so文件,使用的时候直接require进去即可
运行效果:
cmsgpack.pack()可以把多个lua对象序列化成一个二进制msgpack,执行反序化的时候会返回对应数量的lua对象,非常的方便。
有趣的是redis也支持MessagePack,因此结合lua和lua-cmsgpack可以产生不错的化学反应,下面是一个简单的例子(结合OpenResty):
测试返回结果:
在某些场合还是有不错应用场景的。