劉 立,趙建軍,張錦鵬,余 進
(昆明理工大學(xué) 理學(xué)院,云南 昆明 650500)
智慧城市是以互聯(lián)網(wǎng)、物聯(lián)網(wǎng)、電信網(wǎng)、廣電網(wǎng)、無線寬帶網(wǎng)等網(wǎng)絡(luò)組合為基礎(chǔ),以智慧技術(shù)高度集成、智慧產(chǎn)業(yè)高端化發(fā)展、智慧服務(wù)高效便民為主要特征的城市發(fā)展新模式。智慧城市核心是運用信息和通信技術(shù)手段感測、分析、整合城市運行核心系統(tǒng)的各項關(guān)鍵信息[1]。
感知層是智慧城市體系對現(xiàn)實世界進行感知、識別和信息采集的基礎(chǔ)性物理網(wǎng)絡(luò),海量的數(shù)據(jù)在感知層產(chǎn)生[2]。由于智慧城市的飛速發(fā)展,基于物聯(lián)網(wǎng)的應(yīng)用愈加豐富,客戶端和服務(wù)器端數(shù)據(jù)交換方式也越來越多[3]。在相關(guān)AJAX[4](Asynchronous Java Script and XML)應(yīng)用中,XML和JSON是主要數(shù)據(jù)交換格式。為了更好實現(xiàn)數(shù)據(jù)交換,選擇合適的數(shù)據(jù)轉(zhuǎn)換格式對實現(xiàn)數(shù)據(jù)轉(zhuǎn)換、保障應(yīng)用程序性能至關(guān)重要[5]。JSON具有規(guī)則簡單、便于學(xué)習(xí)的特點,且配有多種語言開發(fā)包,在項目中易于使用。無論是使用JavaScript還是其它編程語言,操作JSON的代碼量都相對較少。由于占用空間小、處理速度快,使JSON在AJAX應(yīng)用中優(yōu)勢明顯,在Web服務(wù)與數(shù)據(jù)存儲方面有很大的發(fā)展空間。XML更常見于企業(yè)應(yīng)用。嚴(yán)格的規(guī)范與眾多周邊技術(shù)使XML 應(yīng)用范圍易于擴展,同時大量商業(yè)化應(yīng)用程序支持XML,使非IT人員可以較為容易地編寫、閱讀XML。有些傳感器獲取的文件是以JSON格式存儲于服務(wù)器,為了將傳感器獲取的數(shù)據(jù)進行實時可視化,需要將JSON格式文件實時、動態(tài)地轉(zhuǎn)換為XML格式文件,以便Web端解析調(diào)用,最終實現(xiàn)在前端頁面實時展示。本設(shè)計通過實現(xiàn)動態(tài)JSON轉(zhuǎn)XML并自定義轉(zhuǎn)換JSON文件內(nèi)容,實現(xiàn)感知層獲取數(shù)據(jù)的有效利用。
JSON[6](JavaScript Object Notation)是一種輕量級數(shù)據(jù)交換格式,可在多種語言之間進行數(shù)據(jù)交換,易于讀寫和機器解析、生成。 作為基于JavaScript Programming Language(Standard ECM A - 262 3rd Edition - December 1999)的一個子集,JSON采用完全獨立于語言的文本格式,但因具有類似于C語言家族的特點(C、C++、C#、JAVA、JavaScript、Perl、Python等),使JSON成為理想的數(shù)據(jù)交換語言[7]。
JSON規(guī)則簡單,使用壓縮格式,占用帶寬小,多用于服務(wù)器中,JSON字符串由帶雙引號的Unicode字符集合組成,字符數(shù)量不受限制,單個字符也是一個字符串,其中JSON對象是一個無序的“名稱/值”集合,每個“名稱/值”之間使用逗號“,”分隔。每個名稱使用雙引號“”””括起來,“名稱”后跟著一個冒號“:”,冒號后是值[8-10]。本設(shè)計中用于轉(zhuǎn)換的JSON文本數(shù)據(jù)如下所示:
{"eventId":"1","tid":" C0900000000B6 9D8EA010000000059C5","epc":"04FFC0900000000B 123254321111111155555555555500000000000000000000","firstSeenTime":"1494852436826","lastSeenTime":"1494852437122","seenCount":"28","readerId":"3000000041","antennaNo":"1","monitorId":"HQSJ2LINE","roadNo":"81896","laneNo":"S1E"}。
可擴展標(biāo)識語言[11](Extensible Markup Language, XML)源自標(biāo)準(zhǔn)通用標(biāo)記語言SGML,1995年發(fā)展出雛形,并向W3C提案,于1998年2月發(fā)布為W3C標(biāo)準(zhǔn)(XML1.0)。XML是Internet環(huán)境中依賴內(nèi)容的跨平臺技術(shù),能高效處理現(xiàn)今的結(jié)構(gòu)化文檔信息[12-13]。作為一種允許用戶對標(biāo)記語言進行定義的源語言,XML既可以用于標(biāo)記數(shù)據(jù)也可定義數(shù)據(jù)類型,目前已在電子商務(wù)、無線通信、數(shù)字圖書館、多媒體數(shù)據(jù)庫和資料庫等領(lǐng)域廣泛應(yīng)用[14]。XML使用元素和屬性描述數(shù)據(jù)。在數(shù)據(jù)傳送過程中,XML 始終保留了諸如父/子關(guān)系等數(shù)據(jù)結(jié)構(gòu)。多個應(yīng)用程序可以共享和解析同一個XML文件,不必使用傳統(tǒng)字符串解析或拆解。相反,普通文件不描述每個數(shù)據(jù)段(除頭文件中外),也不保留數(shù)據(jù)關(guān)系結(jié)構(gòu)。使用XML進行數(shù)據(jù)交換可以使應(yīng)用程序更有彈性,因為可以用位置(與普通文件一樣) 或元素名(從數(shù)據(jù)庫)存取XML數(shù)據(jù)。Web服務(wù)讓使用不同操作系統(tǒng)和不同編程語言的人們能夠互相交流和分享數(shù)據(jù),其前提是各Web服務(wù)器使用XML文件在各系統(tǒng)之間交換數(shù)據(jù)。
XML不提供數(shù)據(jù)的顯示方法,只用節(jié)點和屬性描述數(shù)據(jù),因此XML提供了一個標(biāo)記獨立于平臺和語言內(nèi)容的有效方法[15]。使用XSLT[16]語言能輕易地將XML文件轉(zhuǎn)換成各種格式文件,XML能夠運行于不同系統(tǒng)平臺之間和轉(zhuǎn)換成不同格式目標(biāo)文件的能力使其成為內(nèi)容管理應(yīng)用系統(tǒng)中的重要格式,其中XML文件中每個文檔必須有開始和結(jié)束標(biāo)簽。JSON文件轉(zhuǎn)換為XML文件的顯示形式如下所示:
123254321111111155555555555500000000000000000000
010000000059C5
JSON和XML都是開放式數(shù)據(jù)交換,二者既有可通用的方面,也有不同之處。相對于JSON而言,XML屬于重量級數(shù)據(jù)格式[17]。二者都具有與編程語言無關(guān)性的特點,目前常用于異構(gòu)應(yīng)用程序之間數(shù)據(jù)傳遞。具體相關(guān)特性比較如表1所示[18]。
表1 JSON與XML特性比較
針對JSON和XML的優(yōu)缺點,根據(jù)不同情況采用對應(yīng)的文件格式描述數(shù)據(jù)。智慧城市中感知層獲取的數(shù)據(jù)可以利用占用內(nèi)存小的JSON文件保存,而實現(xiàn)數(shù)據(jù)可視化需要利用XML文件進行解析,由于XML利用標(biāo)記語言的特性實現(xiàn)了良好的延展性,在數(shù)據(jù)存儲、擴展以及高級檢索方面具備JSON無法比擬的優(yōu)勢[19]。因此,實現(xiàn)實時展現(xiàn)傳感器獲取數(shù)據(jù)需要實時動態(tài)地將JSON文件轉(zhuǎn)換為XML文件,以便Web前端解析,從而實現(xiàn)在前端頁面顯示。
為實現(xiàn)模塊化、結(jié)構(gòu)化設(shè)計,使系統(tǒng)各部分保持相對獨立,最大程度降低耦合,提高系統(tǒng)擴展性和靈活性[20],首先通過服務(wù)器讀取待處理的JSON文件,然后對其進行序列化轉(zhuǎn)換,生成JSON字符串;再將JSON字符串轉(zhuǎn)換為MAP鍵值對,對其中的內(nèi)容進行修改、刪除,即實現(xiàn)自定義數(shù)據(jù);最后將轉(zhuǎn)換后的JSON文件轉(zhuǎn)為XML文件,保存到指定位置以便Web前端解析使用。為了實現(xiàn)動態(tài)化整個設(shè)計采用JAVA線程處理,即每隔3秒進行刷新,掃描文件夾是否存有JSON文件,如果有則繼續(xù)進行轉(zhuǎn)換。圖1為實現(xiàn)模塊化設(shè)計的流程結(jié)構(gòu)。
圖1 模塊設(shè)計流程
public static File test(File f) {
File[] files = f.listFiles();
for (File file : files) {
File file2 = new File(file.getPath());
if (file2.isDirectory()) {
test(file2);
} else if (file.getName().endsWith(".json")) {
System.out.println(file.getPath());
}
}
return f;
}
本代碼段可以實現(xiàn)從一個指定的文件夾讀取JSON格式的文本文件,從而確定JSON文件動態(tài)轉(zhuǎn)XML文件的數(shù)據(jù)來源。本方法也可擴展應(yīng)用到從文件夾中獲取其它格式的文件。
將JSON文件轉(zhuǎn)換為Map
(1)修改。
monitorId: HQSJ2LINE(YNZZ
lastSeenTime: 1494852437122(2017-05-15 20:47:45,即對獲取的時間字符串進行時間格式化轉(zhuǎn)換。
(2)刪除。刪除不需要轉(zhuǎn)換的JSON信息,例如:firstSeenTime、eventId、antennaNo、readerId,即刪除原有冗余數(shù)據(jù)lastSeenTime和epc。
public static Map
Map
JSONObject json = JSONObject.fromObject(jsonStr);
for (Object k : json.keySet()) {
Object v = json.get(k);
if (null != v) {
map.put(k.toString(), v.toString());
map.put("monitorId", "YNZZ");
String s = map.get("lastSeenTime");
if(s!=null){
System.out.println(s);
long a = Long.parseLong(s);
Date date = new Date(a);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String ptime = sdf.format(date);
map.put("discoveredTime", ptime);}
String epc = map.get("epc");
if(epc!=null){
map.put("rfidPlate", epc);
map.put("tempPlate", epc);}
map.remove("lastSeenTime");
map.remove("firstSeenTime");
map.remove("eventId");
map.remove("antennaNo");
map.remove("readerId");
map.remove("epc");}}
return map;}
Map
JSONObject jsonnew = JSONObject.fromObject (value);
本段代碼是從Map
publicstatic String jsonToXML(JSONObject json) {
JSONObject jobj = JSONObject.fromObject(json);
String xml = SERIALIZER.write(jobj);
return xml; }
本段代碼實現(xiàn)了將JSON字符串轉(zhuǎn)換為XML字符串。
public static void writeStrToFile(String str, String path)
throws IOException {
Scanner input = new Scanner(str + " ");
FileOutputStream fos = new FileOutputStream(path);
while (input.hasNext()) {
String a = input.next();
fos.write((a + " ").getBytes());
}
fos.close();
input.close(); }
本段代碼主要實現(xiàn)將轉(zhuǎn)換后的XML文件存儲到對應(yīng)的文件夾中,以滿足Web調(diào)用。本方法也可實現(xiàn)將字符串保存為其它格式,只需要在保存路徑中添加要保存的后綴即可實現(xiàn)。
采用單線程實現(xiàn)JSON與XML文件的動態(tài)轉(zhuǎn)換,即從本地文件夾讀取JSON文件,再轉(zhuǎn)換為XML文件,然后將獲取的XML文件存儲到本地,在運行過程中動態(tài)刪除已經(jīng)轉(zhuǎn)換的JSON文件,利用線程定時掃描文件夾,如果掃描到新的JSON文件,則重復(fù)以上操作,進行實時轉(zhuǎn)換。
publicvoid run() {
File json = new File("D:\ynzz\ynzziot\jsonxmll");
File[] json1 = test(json).listFiles();
for (File fj : json1) {
File fj2 = new File(fj.getPath());
if (fj2.isDirectory()) {
test(fj2);
} elseif
(fj.getName().endsWith(".json")) {
Scanner scanner = null;
StringBuilder buffer = new StringBuilder();
try {
scanner = new Scanner(fj2, "utf-8");
while (scanner.hasNextLine()) {
buffer.append(scanner.nextLine());}
}catch(FileNotFoundException e) {
} finally {
if (scanner != null) {
scanner.close();}}
System.out.println(
"json=" + buffer.toString());
Map
jsonToMaoString(buffer.toString());
JSONObject jsonnew = JSONObject.fromObject(value);
String xmlnew = jsonToXML(jsonnew);
long time = System.currentTimeMillis();
try {
writeStrToFile(xmlnew,"D:\ynzz\ynzziot\xml2\"+jsonnew.getString("tid")+"ynzz"+time+".xml");
} catch (IOException e1) {
e1.printStackTrace();}
fj2.delete();//原始json文件刪除
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace(); }}} }
publicstaticvoid main(String[] args) throws IOException, JSONException {
while(true){
Thread t1 = new Json2Xml();
t1.start();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace(); } } }
本段代碼主要啟動線程,進行JSON與XML動態(tài)轉(zhuǎn)換,其中采用while(true)循環(huán)實現(xiàn)程序可以保持一直運行狀態(tài),從而使得JSON動態(tài)轉(zhuǎn)換為XML。在實際運用中,將以上實現(xiàn)過程打成jar包,用戶只需啟動jar包即可從某一指定位置讀取JSON文件,然后經(jīng)過jar包轉(zhuǎn)換成XML文件后存儲到另一指定位置。
本文基于智慧城市發(fā)展中感知層的應(yīng)用,對感知層多傳感器源數(shù)據(jù)處理的不同數(shù)據(jù)交換格式進行了研究。通過序列化JSON字符串,深入分析MAP鍵值對,剔除冗余鍵值對,從而將修改后的MAP鍵值對再轉(zhuǎn)為自定義后的JSON字符串,然后在重新自定義JSON字符串的基礎(chǔ)上,生成XML字符串,實現(xiàn)了JSON與XML動態(tài)轉(zhuǎn)換,為開發(fā)者應(yīng)用兩種不同數(shù)據(jù)進行開發(fā)提供了一種有效的數(shù)據(jù)轉(zhuǎn)換方式。