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):
測試返回結果:
在某些場合還是有不錯應用場景的。