AJAX基于JSON和XML的數(shù)據(jù)交換

前言

  1. 相信學(xué)過一段AJAX發(fā)送異步請求的同學(xué)喘沿,一定會非常對數(shù)據(jù)交換感到痛苦,放心椰苟,W3C為我們制定了兩種常用的數(shù)據(jù)交換格式
    • JSON
    • XML
  2. AJAX亂碼問題肠牲,我在這篇文章中也探索了一下

JSON簡介

百度百科介紹:

JSON(JavaScript Object Notation, JS對象簡譜)是一種輕量級的數(shù)據(jù)交換格式。它基于 ECMAScript(European Computer Manufacturers Association, 歐洲計算機協(xié)會制定的js規(guī)范)的一個子集阿弃,采用完全獨立于編程語言的文本格式來存儲和表示數(shù)據(jù)诊霹。簡潔和清晰的層次結(jié)構(gòu)使得 JSON 成為理想的數(shù)據(jù)交換語言。 易于人閱讀和編寫渣淳,同時也易于機器解析和生成脾还,并有效地提升網(wǎng)絡(luò)傳輸效率

JSON基于兩種結(jié)構(gòu)

  • “名稱/值”對的集合(A collection of name/value pairs)入愧。不同的編程語言中鄙漏,它被理解為對象(object),紀(jì)錄(record)棺蛛,結(jié)構(gòu)(struct)怔蚌,字典(dictionary),哈希表(hash table)旁赊,有鍵列表(keyed list)桦踊,或者關(guān)聯(lián)數(shù)組 (associative array)。
  • 值的有序列表(An ordered list of values)终畅。在大部分語言中籍胯,它被實現(xiàn)為數(shù)組(array),矢量(vector)离福,列表(list)杖狼,序列(sequence)。

這些都是常見的數(shù)據(jù)結(jié)構(gòu)妖爷。目前蝶涩,絕大部分編程語言都以某種形式支持它們。這使得在各種編程語言之間交換同樣格式的數(shù)據(jù)成為可能。

JSON具有以下這些形式:

對象(*object*) 是一個無序的“‘名稱/值’對”集合子寓。一個對象以“{”(左括號)開始暗挑,“}”(右括號)結(jié)束。每個“名稱”后跟一個“:”(冒號)斜友;“‘名稱/值’ 對”之間使用“,”(逗號)分隔。

img2023040101.gif

數(shù)組(*array*) 是值(value)的有序集合垃它。一個數(shù)組以“[”(左中括號)開始鲜屏,“]”(右中括號)結(jié)束。值之間使用“,”(逗號)分隔国拇。

img2023040102.gif

值(*value*) 可以是雙引號括起來的字符串(string)洛史、數(shù)值(number)、true酱吝、false也殖、 null、對象(object)或者數(shù)組(array)务热。這些結(jié)構(gòu)可以嵌套忆嗜。

img2023040103.gif

字符串(*string*) 是由雙引號包圍的任意數(shù)量Unicode字符的集合,使用反斜線轉(zhuǎn)義崎岂。一個字符(character)即一個單獨的字符串(character string)捆毫。

JSON的字符串(string)與C或者Java的字符串非常相似。

img2023040104.gif

數(shù)值(*number*) 也與C或者Java的數(shù)值非常相似冲甘。只是JSON的數(shù)值沒有使用八進制與十六進制格式绩卤。

img2023040105.gif

同時,可以在任意標(biāo)記之間添加空白

XML簡介

百度百科介紹

可擴展標(biāo)記語言 (Extensible Markup Language, XML) 江醇,標(biāo)準(zhǔn)通用標(biāo)記語言的子集濒憋,可以用來標(biāo)記數(shù)據(jù)、定義數(shù)據(jù)類型陶夜,是一種允許用戶對自己的標(biāo)記語言進行定義的源語言凛驮。 XML是標(biāo)準(zhǔn)通用標(biāo)記語言 可擴展性良好,內(nèi)容與形式分離,遵循嚴(yán)格的語法要求,保值性良好等優(yōu)點, [1] [7] 。

在電子計算機中律适,標(biāo)記指計算機所能理解的信息符號辐烂,通過此種標(biāo)記,計算機之間可以處理包含各種的信息比如文章等捂贿。它可以用來標(biāo)記數(shù)據(jù)纠修、定義數(shù)據(jù)類型,是一種允許用戶對自己的標(biāo)記語言進行定義的源語言厂僧。 它非常適合萬維網(wǎng)傳輸扣草,提供統(tǒng)一的方法來描述和交換獨立于應(yīng)用程序或供應(yīng)商的結(jié)構(gòu)化數(shù)據(jù)。是Internet環(huán)境中跨平臺的、依賴于內(nèi)容的技術(shù)辰妙,也是當(dāng)今處理分布式結(jié)構(gòu)信息的有效工具鹰祸。早在1998年,W3C就發(fā)布了XML1.0規(guī)范密浑,使用它來簡化Internet的文檔信息傳輸蛙婴。

XML文檔格式

標(biāo)簽)文本內(nèi)容</標(biāo)簽>

元素是由起始標(biāo)簽、元素內(nèi)容和結(jié)束標(biāo)簽組成的尔破。用戶把要描述的數(shù)據(jù)對象放在起始標(biāo)簽和結(jié)束標(biāo)簽之間街图。例如:<姓名>王平</姓名>。無論文本內(nèi)容有多長或者多么復(fù)雜懒构,XML元素中可以再嵌套別的元素餐济,這樣使相關(guān)信息構(gòu)成等級結(jié)構(gòu)。用這樣韻方法定義XML文檔數(shù)據(jù)和數(shù)據(jù)結(jié)構(gòu)胆剧。

除了元素絮姆,XML文檔中出現(xiàn)的有效對象是:聲明、注釋秩霍、根元素篙悯、子元素和屬性。

1.聲明:聲明給XML解析器提供信息前域,使其能夠正確解釋文檔內(nèi)容辕近,它的起始標(biāo)識是“<?”,結(jié)束標(biāo)識是“?>”匿垄。例如XML聲明:<?xml version="1.0" encoding="GB2312"?>移宅,該聲明指明使用的XML版本號和文檔使用的字符集是中文字符集“GB2312”。又如顯示樣式表文件聲明:<?xml-stylesheet type="text/xsl" href="e12_2_1.xsl"?>椿疗,指明按e12_2_1.xsl樣式表文件指定格式顯示本XML文檔漏峰。

2.注釋:注釋是XML文件中用作解釋的字符數(shù)據(jù),XML處理器不對它們進行任何處理届榄。注釋文本被“<!”和“>”標(biāo)記浅乔,注釋可以出現(xiàn)在XML元素問的任何地方,但是不可以嵌套铝条。下邊是一個注釋的例子:<!這是一個注釋>靖苇。

3.根元素和子元素:如果一個元素從文件頭的序言部分之后開始,一直到文件尾班缰,包含了文件中所有的數(shù)據(jù)信息贤壁,我們稱之為根元素。XML元素是可以嵌套的埠忘,那么被嵌套在內(nèi)的元素稱為子元素脾拆。在前面的例子中馒索,<學(xué)生>就是根元素,<編號>就是<學(xué)生>的子元素名船。一個XML文檔中有且僅有一個根元素绰上,其他所有的元素都是它的子元素。

4.屬性:屬性給元素提供進一步的說明信息渠驼,它必須出現(xiàn)在起始標(biāo)簽中蜈块。屬性以名稱/值成對出現(xiàn),屬性名不能重復(fù)渴邦,名稱與取值之間用等號分隔疯趟,取值用引號括起來。例如:<工資 currency="US$">25000</工資>谋梭,其屬性說明了薪水的貨幣單位是美元

5.XML文檔的基本結(jié)構(gòu):XML文檔的基本結(jié)構(gòu)由序言部分和一個根元素組成倦青。序言包括了XML聲明和DTD或XSD聲明瓮床,DTD(Document Type Define,文檔類型定義)和XSD(XML Schema产镐,XML架構(gòu))都是用來描述XML文檔的數(shù)據(jù)結(jié)構(gòu)的隘庄。

6.格式良好的(Well-Formed)XML文檔:一個XML文檔首先應(yīng)當(dāng)是格式良好的,格式良好XML文檔的正式定義位于:http://www.w3.org/TR/REC-xml癣亚。格式良好的XML文檔除了要滿足根元素唯一的特性之外丑掺,還包括:

①起始標(biāo)簽和結(jié)束標(biāo)簽應(yīng)當(dāng)匹配,結(jié)束標(biāo)簽是必不可少的述雾;

②大小寫應(yīng)一致街州,XML對字母的大小寫是敏感的,<employee>和<Employee>是完全不同的兩個標(biāo)簽玻孟,所以結(jié)束標(biāo)簽在匹配時一定要注意大小寫一致唆缴;

③元素應(yīng)當(dāng)正確嵌套,子元素應(yīng)當(dāng)完全包括在父輩元素中黍翎,下面例子就是錯誤嵌套:<A><B></A></B>面徽,正確的嵌套方式為<A><B></B></A>;

④屬性值必須包括在引號中匣掸,元素中的屬性名是不允許重復(fù)的趟紊。

基于JSON的數(shù)據(jù)交換

  • 在WEB前端中,如何將一個json格式的字符串轉(zhuǎn)換成json對象

    var jsonStr = "{\"username\" : \"zhangsan\", \"password\" : \"1233344\"}"
    var jsonObj = JSON.parse(jsonStr)
    console.log(jsonObj.username)
    console.log(jsonObj.password)
    
  • 在后端拼接JSON格式的字符串碰酝,響應(yīng)給前端的瀏覽器

    json.append("[");
    while (rs.next()) {
        // 獲取每個學(xué)生的信息
        String name = rs.getString("name");
        String age = rs.getString("age");
        String addr = rs.getString("addr");
        // 拼接json格式的字符串
        // {"name":"   王五    ","age":    20      ,"addr":"      北京大興區(qū)     "},
        json.append("{\"name\":\"");
        json.append(name);
        json.append("\",\"age\":");
        json.append(age);
        json.append(",\"addr\":\"");
        json.append(addr);
        json.append("\"},");
    }
    jsonStr = json.substring(0, json.length() - 1) + "]";
    

FastJson

fastjson是阿里巴巴的公司內(nèi)技術(shù)大牛開發(fā)出來的霎匈,之后被捐獻(xiàn)給apache軟件基金會,可以在apache官網(wǎng)上下載

拼接JSON格式的字符串太痛苦砰粹,使用阿里巴巴的fastjson組件唧躲,它可以將java對象轉(zhuǎn)換成json格式的字符串

List<Student> studentList = new ArrayList<>();
while (rs.next()) {
    // 取出數(shù)據(jù)
    String name = rs.getString("name");
    int age = rs.getInt("age");
    String addr = rs.getString("addr");
    // 將以上數(shù)據(jù)封裝成Student對象
    Student s = new Student(name, age, addr);
    // 將Student對象放到List集合
    studentList.add(s);
}
// 將List集合轉(zhuǎn)換成json字符串
jsonStr = JSON.toJSONString(studentList);

注意:使用fastjson需要引入fastjson-xxx.jar

基于XML的數(shù)據(jù)交換

  • 注意:如果服務(wù)器端響應(yīng)XML的話造挽,響應(yīng)的內(nèi)容類型需要寫成:

  • 尤其注意:text后面是xml

    response.setContentType("text/xml;charset=UTF-8");
    
  • xml和JSON都是常用的數(shù)據(jù)交換格式

    • XML體積大,解析麻煩弄痹。較少用饭入。
    • JSON體積小,解析簡單肛真,較常用谐丢。
  • 基于XML的數(shù)據(jù)交換,前端代碼

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>使用XML完成數(shù)據(jù)交換</title>
    </head>
    <body>
    <script type="text/javascript">
        window.onload = function(){
            document.getElementById("btn").onclick = function(){
                // 1.創(chuàng)建XMLHTTPRequest對象
                var xhr = new XMLHttpRequest();
                // 2.注冊回調(diào)函數(shù)
                xhr.onreadystatechange = function () {
                    if (this.readyState == 4) {
                        if (this.status == 200) {
                            // 服務(wù)器端響應(yīng)了一個XML字符串蚓让,這里怎么接收呢乾忱?
                            // 使用XMLHTTPRequest對象的responseXML屬性,接收返回之后历极,可以自動封裝成document對象(文檔對象)
                            var xmlDoc = this.responseXML
                            //console.log(xmlDoc)
                            // 獲取所有的<student>元素窄瘟,返回了多個對象,應(yīng)該是數(shù)組趟卸。
                            var students = xmlDoc.getElementsByTagName("student")
                            //console.log(students[0].nodeName)
                            var html = "";
                            for (var i = 0; i < students.length; i++) {
                                var student = students[i]
                                // 獲取<student>元素下的所有子元素
                                html += "<tr>"
                                html += "<td>"+(i+1)+"</td>"
                                var nameOrAge = student.childNodes
                                for (var j = 0; j < nameOrAge.length; j++) {
                                    var node = nameOrAge[j]
                                    if (node.nodeName == "name") {
                                        //console.log("name = " + node.textContent)
                                        html += "<td>"+node.textContent+"</td>"
                                    }
                                    if (node.nodeName == "age") {
                                        //console.log("age = " + node.textContent)
                                        html += "<td>"+node.textContent+"</td>"
                                    }
                                }
                                html += "</tr>"
                            }
                            document.getElementById("stutbody").innerHTML = html
                        }else{
                            alert(this.status)
                        }
                    }
                }
                // 3.開啟通道
                xhr.open("GET", "/ajax/ajaxrequest6?t=" + new Date().getTime(), true)
                // 4.發(fā)送請求
                xhr.send()
            }
        }
    </script>
    <button id="btn">顯示學(xué)生列表</button>
    <table width="500px" border="1px">
        <thead>
        <tr>
            <th>序號</th>
            <th>姓名</th>
            <th>年齡</th>
        </tr>
        </thead>
        <tbody id="stutbody">
        <!--<tr>
            <td>1</td>
            <td>zhangsan</td>
            <td>20</td>
        </tr>
        <tr>
            <td>2</td>
            <td>lisi</td>
            <td>22</td>
        </tr>-->
        </tbody>
    </table>
    </body>
    </html>
    
  • 基于XML的數(shù)據(jù)交換蹄葱,后端java程序:

    @WebServlet("/ajaxrequest6")
    public class AjaxRequest6Servlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            // 注意:響應(yīng)的內(nèi)容類型是XML。
            response.setContentType("text/xml;charset=UTF-8");
            PrintWriter out = response.getWriter();
            StringBuilder xml = new StringBuilder();
            xml.append("<students>");
            xml.append("<student>");
            xml.append("<name>zhangsan</name>");
            xml.append("<age>20</age>");
            xml.append("</student>");
            xml.append("<student>");
            xml.append("<name>lisi</name>");
            xml.append("<age>22</age>");
            xml.append("</student>");
            xml.append("</students>");
            
            out.print(xml);
        }
    }
    

AJAX亂碼問題

  • 測試內(nèi)容:

    • 發(fā)送ajax get請求
      • 發(fā)送數(shù)據(jù)到服務(wù)器锄列,服務(wù)器獲取的數(shù)據(jù)是否亂碼图云?
      • 服務(wù)器響應(yīng)給前端的中文,會不會亂碼邻邮?
    • 發(fā)送ajax post請求
      • 發(fā)送數(shù)據(jù)到服務(wù)器竣况,服務(wù)器獲取的數(shù)據(jù)是否亂碼?
      • 服務(wù)器響應(yīng)給前端的中文筒严,會不會亂碼丹泉?
  • 包括還要測試tomcat服務(wù)器的版本:

    • tomcat10和tomcat9都要進行測試。
  • 測試結(jié)果:

    • 對于tomcat10來說萝风,關(guān)于字符集嘀掸,我們程序員不需要干涉,不會出現(xiàn)亂碼规惰。

    • 對于tomcat9來說呢睬塌?

      • 響應(yīng)中文的時候,會出現(xiàn)亂碼歇万,怎么解決揩晴?

        response.setContentType("text/html;charset=UTF-8");
        
      • 發(fā)送ajax post請求的時候,發(fā)送給服務(wù)器的數(shù)據(jù)贪磺,服務(wù)器接收之后亂碼硫兰,怎么解決?

        request.setCharacterEncoding("UTF-8");
        

參考文獻(xiàn)

  1. XML - MBA智庫百科 (mbalib.com)
  2. fastjson詳解
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末寒锚,一起剝皮案震驚了整個濱河市劫映,隨后出現(xiàn)的幾起案子违孝,更是在濱河造成了極大的恐慌,老刑警劉巖泳赋,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件雌桑,死亡現(xiàn)場離奇詭異,居然都是意外死亡祖今,警方通過查閱死者的電腦和手機校坑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來千诬,“玉大人耍目,你說我怎么就攤上這事⌒彀螅” “怎么了邪驮?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長傲茄。 經(jīng)常有香客問我耕捞,道長,這世上最難降的妖魔是什么烫幕? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮敞映,結(jié)果婚禮上昵宇,老公的妹妹穿的比我還像新娘华蜒。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布恳谎。 她就那樣靜靜地躺著,像睡著了一般楔脯。 火紅的嫁衣襯著肌膚如雪喇肋。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天档桃,我揣著相機與錄音枪孩,去河邊找鬼。 笑死藻肄,一個胖子當(dāng)著我的面吹牛蔑舞,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播嘹屯,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼攻询,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了州弟?” 一聲冷哼從身側(cè)響起钧栖,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤低零,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后拯杠,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體掏婶,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年阴挣,在試婚紗的時候發(fā)現(xiàn)自己被綠了气堕。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,841評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡畔咧,死狀恐怖茎芭,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情誓沸,我是刑警寧澤梅桩,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站拜隧,受9級特大地震影響宿百,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜洪添,卻給世界環(huán)境...
    茶點故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一垦页、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧干奢,春花似錦痊焊、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至逛尚,卻和暖如春垄惧,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背绰寞。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工到逊, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人克握。 一個月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓蕾管,卻偏偏與公主長得像,于是被迫代替她去往敵國和親菩暗。 傳聞我的和親對象是個殘疾皇子掰曾,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,781評論 2 354

推薦閱讀更多精彩內(nèi)容