<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    您好朋友,感謝您關注xiaosilent,我在blogjava的博客已經停止更新,請訪問http://kuan.fm了解我的最新情況,謝謝!
    隨筆-82  評論-133  文章-0  trackbacks-0
    JSON簡介

    時間:2007-03-27
    作者:Daniel Rubio
    瀏覽次數: 877
    本文關鍵字:JSON, JavaScript Object Notation, JavaScript, XML, Dev Toolbox, WebLogic Server, Daniel Rubio

    摘要

      XML——這種用于表示客戶端與服務器間數據交換有效負載的格式,幾乎已經成了Web services的同義詞。然而,由于Ajax和REST技術的出現影響了應用程序架構,這迫使人們開始尋求`XML的替代品,如:JavaScript Object Notation(JSON)。

      JSON 作為一種更輕、更友好的 Web services客戶端的格式(多采用瀏覽器的形式或訪問 REST風格 Web服務的Ajax應用程序的形式)引起了 Web 服務供應商的注意。

      本文將闡述JSON在Web services設計中備受推崇的原因,以及它作為XML替代方案的主要優勢和局限性。文中還會深入探討:隨著相應的Web 服務客戶端選擇使用JSON,如何才能便捷地在Java Web services中生成JSON輸出。

    XML的十字路口: 瀏覽器和 Ajax

      XML設計原理已經發布了將近十年。時至今日,這種標記語言已經在廣闊的軟件應用領域中占據了主導地位。從Java、.NET等主流平臺中的配置和部署描述符到應用集成場景中更復雜的應用,XML與生俱來的語言無關性使之在軟件架構師心目中占據著獨特的地位。但即便最著名的XML權威也不得不承認:在某些環境中,XML的使用已經超出了它自身能力的極限。

      圍繞Ajax原理構建的那些Web應用程序最能說明XML的生存能力,從這一點來看,一種新的有效負載格式的發展壯大也得益于XML。這種新的有效負載格式就是JavaScript Object Notation (JSON)。在探索這種新的標記語言的復雜性之前,首先來分析一下在這種獨特的設計形式中,XML具有哪些局限性。

      Ajax建立了一個用于從遠程Web services發送和接收數據的獨立信道,從而允許Web程序執行信道外(out-of-band)客戶端/服務器調用。通俗地說,Ajax程序中的更新和導航序列在典型的客戶端/服務器環境之外完成,在后臺(即信道外)接受到信息后,必須進行一次完整的屏幕刷新。更多背景信息,請參閱David Teare的 Ajax簡介(Dev2Dev)。

      這些應用程序更新通常是通過REST風格(RESTful)Web services獲得的,一旦被用戶的瀏覽器接收到,就需要整合到HTML頁面的總體布局之中,這正是XML發揮強大力量的場合。盡管近年來,腳本語言支持和插件支持已使大多數主流瀏覽器的功能得到了強化,但許多編程任務依然難于開展,其中之一就是操縱或處理文本,這通常是使用DOM實現的。

      采用DOM的復雜性源于其基于函數的根,這使得對數據樹的簡單修改或訪問都需要進行無數次方法調用。此外,眾所周知,DOM在各種瀏覽器中的實現細節不盡相同,這一過程將帶來極為復雜的編程模式,其跨瀏覽器兼容性出現問題的可能性極大。接下來的問題顯而易見,那就是:如何使一種標記語言輕松集成到HTML頁面中以滿足Ajax的要求?

      問題的答案就是:利用所有主流瀏覽器中的一種通用組件——JavaScript引擎。XML需要使用DOM之類的機制來訪問數據并將數據整合到布局之中,采用這種方法,我們不再使用像XML這樣的格式來交付Ajax更新,而是采用一種更為簡單直觀的方式,采用JavaScript引擎自然匹配的格式——也就是JSON。

      既然已經明確了JSON與XML和Ajax之間的關系,下面將進一步探討JSON背后的技術細節。

    JSON剖析:優點和不足

      對于JSON,首先要明白JSON和XML一樣也是一種簡單文本格式。相對于XML,它更加易讀、更便于肉眼檢查。在語法的層面上,JSON與其他格式的區別是在于分隔數據的字符,JSON中的分隔符限于單引號、小括號、中括號、大括號、冒號和逗號。下圖是一個JSON有效負載:

    				{"addressbook": {"name": "Mary Lebow",
    ?????? "address": {
    ?????????? "street": "5 Main Street"
    ?????????? "city": "San Diego, CA",
    ?????????? "zip": 91912,
    ?????? },
    ?????? "phoneNumbers": [
    ?????????? "619 332-3452",
    ?????????? "664 223-4667"
    ?????? ]
     }
    }
    		

      將上面的JSON有效負載用XML改寫,如下:

    				<addressbook>
     <name>Mary Lebow</name>
     <address> 
    ?????? <street>5 Main Street</street>
    ?????? <city zip="91912"> San Diego, CA </city>
    ?????? <phoneNumbers>
    ???????? <phone>619 332-3452</phone>
    ???????? <phone>664 223-4667</phone>
    ?????? </phoneNumbers>
     </address>
    </addressbook>
    		

      是不是很相似?但它們并不相同。下面將詳細闡述采用JSON句法的優點和不足。

    優點

      乍看上去,使用JSON的數據分隔符的優點可能并不那么明顯,但存在一個根本性的緣由:它們簡化了數據訪問。使用這些數據分隔符時, JavaScript引擎對數據結構(如字符串、數組、對象)的內部表示恰好與這些符號相同。

      這將開創一條比DOM技術更為便捷的數據訪問途徑。下面列舉幾個JavaScript代碼片段來說明這一過程,這些代碼片段會訪問先前的JSON代碼片段中的信息:

    • 訪問JSON中的名稱: addressbook.name
    • 訪問JSON中的地址: addressbook.address.street
    • 訪問JSON中的電話號碼第一位:addressbook.address.phoneNumbers[0]

      如果您具備DOM編程經驗,就能很快地看出區別;新手可以參看 Document Object Model 的這一外部資源,這里提供了關于數據導航的實例。

      JSON的另一個優點是它的非冗長性。在XML中,打開和關閉標記是必需的,這樣才能滿足標記的依從性;而在JSON中,所有這些要求只需通過一個簡單的括號即可滿足。在包含有數以百計字段的數據交換中,傳統的XML標記將會延長數據交換時間。目前還沒有正式的研究表明JSON比XML有更高的線上傳輸效率;人們只是通過簡單的字節數比較發現,對于等效的JSON和XML有效負載,前者總是小于后者。至于它們之間的差距有多大,特別是在新的XML壓縮格式下它們的差距有多大,有待進一步的研究。

      此外,JSON受到了擅長不同編程語言的開發人員的青睞。這是因為無論在Haskell中或 Lisp中,還是在更為主流的C#和PHP中,開發都可以方便地生成JSON(詳見 參考資料)。

    不足

      和許多好東西都具有兩面性一樣,JSON的非冗長性也不例外,為此JSON丟失了XML具有的一些特性。命名空間允許不同上下文中的相同的信息段彼此混合,然而,顯然在JSON中已經找不到了命名空間。JSON與XML的另一個差別是屬性的差異,由于JSON采用冒號賦值,這將導致當XML轉化為JSON時,在標識符(XML CDATA)與實際屬性值之間很難區分誰應該被當作文本考慮。

      另外,JSON片段的創建和驗證過程比一般的XML稍顯復雜。從這一點來看,XML在開發工具方面領先于JSON。盡管如此,為了消除您對這一領域可能存在的困惑,下節將介紹一些最為成熟的JSON開發。

    從Web services生成JSON輸出

      既然JSON的首要目標是來自瀏覽器的信道外請求,那么我們選擇REST風格(RESTful)Web服務來生成這些數據。除了用典型業務邏輯探究Web服務之外,還將采用特定的API把本地Java結構轉化為JSON格式(詳見 參考資料)。首先,下面的Java代碼用來操縱Address對象:

    // Create addressbook data structure
    SortedMap addressBook = new TreeMap();
    
    // Create new address entries and place in Map 
    // (See download for Address POJO structure)
    Address maryLebow = new Address("5 Main Street","San Diego, CA",91912,"619-332-3452","664-223-4667"); 
    addressBook.put("Mary Lebow",maryLebow);
    
    Address amySmith = new Address("25 H Street","Los Angeles, CA",95212,"660-332-3452","541-223-4667"); 
    addressBook.put("Sally May",amySmith);
    
    Address johnKim = new Address("2343 Sugarland Drive","Houston, TX",55212,"554-332-3412","461-223-4667"); 
    addressBook.put("John Kim",johnKim);
    
    Address richardThorn = new Address("14 68th Street","New York, NY",,12452,"212-132-6182","161-923-4001"); 
    addressBook.put("Richard Thorn",richardThorn);

      該Java結構在哪里生成并不重要(可能是在JSP、Servlet、EJB或POJO中生成),重要的是,在REST風格Web 服務中有權使用這些數據。如下示:

    				// Define placeholder for JSON response
    String result = new String();
    
    // Get parameter (if any) passed into application 
    String from = request.getParameter("from");
    String to = request.getParameter("to");
    
    try { 
    ?????? // Check for parameters, if passed filter address book 
    ?????? if(from != null && to != null) { 
    ???????? // Filter address book by initial 
    ???????? addressBook = addressBook.subMap(from,to);
    ?????? } 
    
    ????? // Prepare the convert addressBook Map to JSON array 
    ????? // Array used to place numerous address entries 
    ????? JSONArray jsonAddressBook = new JSONArray();
     
    ????? // Iterate over filtered addressBook entries 
    ????? for (Iterator iter = addressBook.entrySet().iterator(); iter.hasNext();)???? { 
    
    ??????? // Get entry for current iteration?????????? 
    ??????? Map.Entry entry = (Map.Entry)iter.next();
    ??????? String key = (String)entry.getKey();
    ??????? Address addressValue = (Address)entry.getValue();
    
    ??????? // Place entry with key value assigned to "name" 
    ??????? JSONObject jsonResult = new JSONObject();
    ??????? jsonResult.put("name",key);
    
    ??????? // Get and create address structure corresponding to each key 
    ??????? // appending address entry in JSON format to result 
    ??????? String streetText = addressValue.getStreet();
    ??????? String cityText = addressValue.getCity();
    ??????? int zipText = addressValue.getZip();
    ??????? JSONObject jsonAddress = new JSONObject();
    ??????? jsonAddress.append("street",streetText);
    ??????? jsonAddress.append("city",cityText);
    ??????? jsonAddress.append("zip",zipText);
    ??????? jsonResult.put("address",jsonAddress);
    
    ??????? // Get and create telephone structure corresponding to each key 
    ??????? // appending telephone entries in JSON format to result 
    ??????? String telText = addressValue.getTel();
    ??????? String telTwoText = addressValue.getTelTwo();
    ??????? JSONArray jsonTelephones = new JSONArray();
    ??????? jsonTelephones.put(telText);
    ??????? jsonTelephones.put(telTwoText);
    ??????? jsonResult.put("phoneNumbers",jsonTelephones);
    
    ??????? // Place JSON address entry in global jsonAddressBook 
    ??????? jsonAddressBook.put(jsonResult);
    ????? } // end loop over address book 
    
    ??????? // Assign JSON address book to result String???? 
    ??????? result = new JSONObject().put("addressbook",jsonAddressBook).toString();
    
    ???? } catch (Exception e) { 
    ??????? // Error occurred???????? 
    ???? }
    
    		

      為了便于說明,我們已將這段代碼將置入JSP(restservice.jsp)中。如果它真是一段程序,那么類似這樣的代碼也會出現在servlet或helper類中。 REST風格Web服務首先提取兩個通過URL請求傳遞給它的輸入參數,根據這些值過濾現有的地址簿以適應請求。過濾過地址簿后,即可開始循環檢查Java映射中的每個條目。

      您會注意到,在循環內部,json.org API被廣泛用于將本地Java格式轉化為JSON字符串。雖然僅使用了少量類(即JSONArray和JSONObject),但API提供的轉換方法相當廣泛,甚至能將XML結構轉換成JSON輸出。但回到我們的Web服務,一旦循環遍歷了所有條目,那么變量“result”會包含準備返回給請求方的地址簿的JSON同等部分。

      既然已經生成了JSON輸出,下面來看看等式的另一邊:瀏覽器應用程序中JSON有效負載的使用。

    JSON有效負載的使用

      作為基于瀏覽器的客戶端,我們的設計中大部分工作都是在HTML、JavaScript加上附加的JavaScript 框架下完成的。例如利用Prototype庫輕松創建跨瀏覽器樣式的Ajax調用。下面的清單包含了我們的應用程序的第一部分,以及相應的JavaScript函數。

    				<html> 
    <head> 
    <title> JSON Address Book </title> 
    <script type="text/javascript" src="prototype-1.4.0.js"></script> 
    <script type="text/javascript"> 
    // Method invoked when user changes letter range
    function searchAddressBook() {
    
    ???? // Select values from HTML select lists
    ???? var fromLetter = $F('fromLetter');
    ???? var toLetter = = $F('toLetter');
    
    ???? // Prepare parameters to send into REST web service
    ???? var pars = 'from=' + fromLetter + '&to=' + toLetter;
    ???? // Define REST web service URL 
    ???? var url = 'restservice.jsp';
    
    ???? // Make web service Ajax request via prototype helper, 
    ???? // upon response, call showResponse method??? 
    ???? new Ajax.Request( url, { method: 'get', parameters: pars, 
    ????????????????????????????? onComplete: showResponse });
    }
    
    </script> 
    </head>
    		

      首先導入了prototype庫,該庫用于促進對REST風格Web服務的Ajax調用。接下來是searchAddressBook()函數,當用戶修改其下所示的HTML選擇列表時,將會觸發此函數。該函數被觸發后,用戶將會獲得HTML選擇列表中已選中的選項,并將其放入兩個用于過濾地址簿的變量中,隨后定義一個指向REST風格服務URL restservice.jsp的附加變量。

      此方法中還包括借助原型函數new Ajax.Request( url, { method: 'get', parameters: pars, onComplete: showResponse }); 的實際Ajax Web服務調用;表明了對相關URL的一個請求,其請求參數包含在pars中;最后一旦Ajax請求終止,即執行showResponse()。

      下面以showResponse()為例說明用于評估JSON有效負載并將其放入HTML主體布局環境中的的必要代碼。

    				// Method invoked when page receives Ajax response from REST web service 
    function showResponse(originalRequest) {
    ????? // Get JSON values 
    ????? jsonRaw = originalRequest.responseText;
    ????? // Eval JSON response into variable 
    ????? jsonContent = eval("(" + jsonRaw + ")");
    
    ????? // Create place holder for final response?????? 
    ????? finalResponse = "<b>" + jsonContent.addressbook.length + 
    ????????????????????? " matches found in range</b><br/>";
    
    ????? // Loop over address book length.
    ????? for (i = 0; i < jsonContent.addressbook.length; i++) {
    ?????????? finalResponse += "<hr/>";
    ?????????? finalResponse += "<i>Name:</i> " + jsonContent.addressbook[i].name + "<br/>";???????????? 
    ?????????? finalResponse += "<i>Address:</i> " + jsonContent.addressbook[i].address.street + " -- " + 
    ???????????????????????????? jsonContent.addressbook[i].address.city + "," +????????????? 
    ???????????????????????????? jsonContent.addressbook[i].address.zip + ".<br/>";???????????? 
    ?????????? finalResponse += "<i>Telephone numbers:</i> " + jsonContent.addressbook[i].phoneNumbers[0] + " & " + 
    ?????????? jsonContent.addressbook[i].phoneNumbers[1] + ".";???????????? 
    ????? }
    
    ????? // Place formatted finalResponse in div element
    ????? document.getElementById("addressBookResults").innerHTML = finalResponse;
     }
    		

      此方法的輸入參數是REST風格Web服務在調用時返回的響應。既然預先已經知道需要處理JSON字符串,那么可以利用JavaScript eval()函數,將這個JSON字符串放入內存,并允許數據訪問,正是這樣的簡便性促使開發人員使用JSON。完全不需要進行解析,一個簡單的eval()即可得到JavaScript結構,我們可以像操縱其他任何JavaScript結構一樣地去操縱它。

      一旦JSON響應經過eval處理,將創建一個JavaScript循環來提取每個地址條目,并將各個匹配項放入一個名為finalResponse的容器變量中。而這個容器變量本身包含所有必要的格式,用于在頁面布局中顯示最終地址簿。循環結束時,匹配項也通過document.getElementById("addressBookResults").innerHTML放置完畢。

      最后,為了保持完整,頁面的實際布局由這些代碼組成:

    				<body> 
    <h4 style="text-align:left">Request address book matches:</h4>
    <table style="text-align:left" cellpadding="15"><tr><td valign="top">From:<br/>
    <select id="fromLetter" size="15" onchange="searchAddressBook()">
     <option>A</option>
     ...
     <option>Z</option>
    </select>
    </td><td valign="top">To:<br/>
    <select id="toLetter" size="15" onchange="searchAddressBook()">
     <option>A</option>
     ...
     <option>Z</option>
    </select>
    </td><td valign="top">
    <h5> Results </h5> 
    <div style="text-align:left" id="addressBookResults">Please select range</div>
    </td></tr>
    </table>
    </body> 
    
    		

      上面的代碼清單中最值得一提的是HTML選擇列表,因為修改觸發器Java程序需要調用信道外Ajax請求。其次,<div>元素就是放置格式化后的JSON響應的地方。??????????????????????????????????????????????????????????????????????????

    JSON適合您嗎

      就像在軟件設計中編程語言的選擇一樣,JSON的選擇與否取決于您自身的需求。如果Web services使用者將在傳統、功能完備的編程環境(如Java 、.NET、PHP、Ruby等)中創建,那么完全可以不使用JSON。給定大多數編程語言環境的無限制能力可提供完整的配置控制權(更不必說對定制庫、分析器或helper類的訪問),那么JSON與XML及其他Web services有效載荷之間的差別可以忽略不計。

      反之,如果Web services使用者被限制在瀏覽器環境之外,那么JSON是值得認真考慮的對象。 在瀏覽器中使用Web services并非興趣使然,而是實際業務需求。如果這時需要一個加載數據時不會出現延遲/刷新的“漂亮的Web 2.0界面”, 就不得不在瀏覽器中嵌入Ajax和Web services技術。

      在這種情況下,您不僅受限于通過網絡訪問處理環境,而且還會受到隨機用戶的限制,迫使經驗豐富的開發人員用最普遍的工具在瀏覽器中處理文本,例如:前述的DOM,與訪問JSON樹相比,DOM使用起來非常困難。

    示例代碼

      您可下載與本文相關的代碼。

      安裝之前先解壓下載得到的文件,將addressbook.html,prototype-1.4.0.js和restservice.jsp放入任意程序的目錄下。將內含的json.jar復制到所選程序的/WEB-INF/lib目錄下。訪問<yourhost>/<yourappdir>/addressbook.html,并在HTML列表中進行選擇。一切就緒,可以運行JSON了!

    結束語

      盡管 “Ajax”中的“x”代表XML,Web services也通過堅持使用XML格式而成為主流,但這并不意味著這種方式無懈可擊。在文本處理方面,XML在Ajax程序的應用中已經暴露出一些缺點。在這種情形下,JSON逐漸成為引人注目的XML替代方案。

      通過對JSON語法優缺點的論述,以及對如何從REST風格Web services創建JSON輸出、如何將其嵌入Web頁面布局等問題的介紹,您現在應該能夠為最終用戶提供支持JSON的Web services,接觸當前提供的大量利用這一極具前途的格式的Web services。

    參考資料

    • Ajax簡介(David Teare,Dev2Dev,2005年8月)——介紹Ajax的相關技術背景
    • JSON in Java ——介紹使用Java API將本地Java結構轉換成JSON輸出
    • Prototype ——介紹用于創建Ajax應用程序的JavaScript框架
    • JSON.org ——JSON主頁,其中包含可生成JSON的各種語言庫的資源和鏈接
    作者簡介
    Daniel Rubio 是一名軟件顧問,具有十余年的企業軟件開發經驗。近期,他創辦了Mashup Soft公司,開始專攻為Mashup使用Web services的有關方面。


    另一個JSON的介紹:http://m.tkk7.com/woxingwosu/archive/2008/01/24/133301.html
    posted on 2007-05-23 18:12 xiaosilent 閱讀(997) 評論(0)  編輯  收藏

    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 成年女人喷潮毛片免费播放| 亚洲无人区午夜福利码高清完整版 | 毛片在线免费视频| 亚洲国产欧美国产综合一区 | 国产免费人成视频尤勿视频| 亚洲国产成人精品无码区花野真一| 日韩免费高清视频| 国产午夜不卡AV免费| 在线精品亚洲一区二区| 91手机看片国产永久免费| 亚洲heyzo专区无码综合| 亚洲熟妇中文字幕五十中出| 在线日本高清免费不卡| 国产成人毛片亚洲精品| 免费视频专区一国产盗摄| 亚洲成AV人片在WWW| 91麻豆精品国产自产在线观看亚洲| 在线看片免费人成视频久网下载| 在线观看亚洲人成网站| 在线永久免费观看黄网站| 国产精品美女免费视频观看| 99亚洲精品高清一二区| 在线观看无码AV网站永久免费| 亚洲一本一道一区二区三区| 午夜一区二区免费视频| 婷婷国产偷v国产偷v亚洲| 78成人精品电影在线播放日韩精品电影一区亚洲 | 两性色午夜免费视频| 亚洲人成77777在线播放网站不卡| 免费观看国产精品| 97视频免费观看2区| 国产成人高清亚洲一区91| 亚洲国产高清在线| 免费国产怡红院在线观看| 污污网站免费观看| 国产精品亚洲精品日韩电影| 久久久久亚洲AV无码观看| jjzz亚洲亚洲女人| 男男AV纯肉无码免费播放无码 | 亚洲国产一成久久精品国产成人综合 | 久久久久亚洲AV无码专区体验|