1. 程式人生 > >【Java Web】: JSON 資料格式詳解

【Java Web】: JSON 資料格式詳解

  JSON (JavaScript Object Notation) JavaScript物件圖,它是由Douglas Crockford(道格拉斯·克洛克福特)發明的。

  JSON與XML一樣都是做傳遞資料使用, 在目前的網路應用下傳遞資料主要有兩種,一種是XML,一種就是JSON資料,而JSON使用數量還更多。

  JSON是一種文字格式(注意不是文件格式!),它是獨立存在的而不侷限於某一種語言,它是一種很理想的資料交換格式。

  JSON基於兩種結構來構建:
    1. 名字/鍵值對。在Java中類似MAP
    2. 它是一個有序值的列表。
  這是一種很常見的資料結構,也相容了現在大部分的程式設計語言,這就使得不同的程式設計語言通過上面兩種資料結構來進行資料交換而變得很有意義。

1. JSON各種資料的格式說明

1) object(物件)

JSON中物件是一個無序的 名/值 對。一個物件用"{" 開始和"}"號結束。名和值之間用":"隔開,如果有多個物件需要用","隔開。

類似{"name":"value", "flag":false}


【注意】----------------------------

在JavaScript中物件的表示形式是
var s = {'a':'b', c:false}
s.a 打印出b
s.b 打印出false
上面就是一種很簡單的資料表示格式,是在js中表示的,但是在JSON資料格式中我們還是嚴格按照標準用雙引號來。Json資料格式可以表示成很複雜的資料結構,包括可以巢狀,而且可以相容陣列這個概念,數組裡面裡面可以存放物件,物件裡面又可以存放陣列。

2) array(陣列)

JSON中陣列是一個有序的元素的集合,一個數組以"["開始和以"]"結束,不同的元素用","隔開。

類似{"students":[{"name":"AHuier", "age":23}, {"name":"Jack", "age":22}]}


【注意】----------------------------

在JavaScript中陣列的表示形式是

var s = ['a','b','c',false]

這僅僅是在js中是如此表示的,在json資料格式的表示方法還是不一樣的。

3) value(值)

值可以是一個在雙引號裡面的字串,或者是一個數字,或者是boolean型別(true, false)或者為null,或者是一個物件或者是一個數組,這些結構還可以進行巢狀。

4) string(字串)

字串是一個零或者多個Unicode字元組成的序列,它們包含於雙引號中,可以使用反斜槓轉義。一個字元可以看做是長度為1的字串, 這很像C或者Java語言中的string.

類似{"name":"AHuier", "age":"23"}

5) number(數字)

數字和C或者Java語言類似,除了JSON不支援八進位制和十六進位制的資料格式。

空格可以被隨意插入到任意兩個名值對之間。

2. JSON 與 XML

   1) JSON與XML都可以進行資料的傳輸,XML除了可以做資料的傳輸之外,可以作為一個小型的資料格式來儲存資料,但是JSON僅僅是用來作為資料傳輸的,它不會儲存資料。

   2) Json傳遞的資料量很小,特別是傳輸很多資料的時候,可以有效的減少頻寬。

   3) JSON不是一個文件的格式,Json也不是一種標記語言,JSON也不是一種通用的可序列化的格式.它僅僅是一種資料格式。

   4) XML中存在名稱空間,但是在JSON中是不存在名稱空間的概念的(因為它與XML不同沒有DTD這種檢查格式的規範)。在JSON中其實每一個物件都可以作為一個名稱空間。

   5) JSON的MIME Media Type媒體型別是application/json,這個用在什麼地方呢?

      在sevelet中,傳送給客戶端的格式通常是text/html,那如果是application/json 這樣的話客戶端瀏覽器在接受到響應頭之後,它解析到此發現它是一個Json的陣列格式,它就會以JSON的方式去處理。如果是 xml就是 text/xml 的方式去處理XML。

   注意:任何的XML都可以通過JSON的資料格式表示出來。JSON的編碼格式統一是Unicode的格式,它的編碼預設是utf-8.

例如:講如下的XML格式轉換為JSON格式

XML格式:

    <users>
        <user gender="male">
            <username>AHuier</username>
            <age>23</age>
            <address>XIAMEN</address>
        </user>
        <user>
            <username>AHuier7</username>
            <age>23</age>
            <address>BEIJNG</address>
        </user>
    </users>

JSON格式:

    [{"username":"AHuier", "age":23, "address":"XIAMEN", "gender":"male"}{"username":"AHuier7", "age":23, "address":"BEIJING"}]

【注意】:這裡XML中的user的屬性 gender在JSON中我們也可以將其當成一個物件名值對來看待。

3. JSON 與 XML的轉換,如下,將下面的XML文件轉換為JSON的資料格式。

   XML格式:

<section>
    <title>Book-Signing Event</title>
    <signing>
        <author title="Mr" name="Vikiram Seth" />
        <book title="A Suitable Boy" price="$22.95" />
    </signing>
    <signing>
        <author title="Dr" name="Oliver Sacks" />
        <book title="The Island of the Color-Blind" price="$12.95" />
    </signing>  
</section>

轉換後JSON格式,在HTML檔案中JS的形式寫出,json.html

<script type="text/javascript">
var s = {"section":
    {
        "title":"Book-Signing Event",
        "signing":[
            {
                "author":{"title":"Mr", "name":"Vikiram Seth"},
                "book":{"title":"A Suitable Boy", "price":"$22.95"}
            },
            {
                "author":{"title":"Dr", "name":"Oliver Sacks"},
                "book":{"title":"The Island of the Color-Blind", "price":"$12.95"}
            }
        ]
    }
};

alert(s.section.title);
alert(s.section.signing[0].author.title);
</script>

【程式執行結果】:執行json.html檔案

1. alert(s.section.title);請求"Book-Signing Event" 如下圖所示


2. alert(s.section.signing[0].author.title);請求"Mr" 如下圖所示

4. JSON 資料格式在Java中應用。

1) 首先從GitHub中下載JSON的包,將其拷貝到專案中放置在新建的一個獨立包中如org.json包中,這樣保持它的獨立性。

    檢視官網org.java中關於api的說明,我們比較常用的是JSONObject.java 與 JSONArray.java這兩個類。

檢視JSONObject.java的構造方法 它可以接受map物件[public JSONObject(java.util.Map map)]轉換成json例項,也可以接受一個字串[public JSONObject(java.lang.String source)]將其轉換成json的例項。如下圖所示

2) 常用JSON的API說明:在官網www.json.org中的 org.json 專案模組中(Java中解析json的開源專案很多,我們這裡主要運用第一個org.json的專案,這個專案也是道格拉斯寫的Java程式碼)

   public JSONObject(java.lang.String source) throws JSONException
     接受一個帶有JSON物件格式的字串,將其構造成json物件。(這樣就可以通過JSONObject類裡面的各種getXXX()方法將json裡面對應名的值取出。)
   引數:
     source - A string beginning with { (left brace) and ending with } (right brace).

   public JSONArray(java.lang.String source) throws JSONException
     接受一個帶有JSON陣列格式的字串,將其構造成json陣列。
   引數:
     source - A string that begins with [ (left bracket) and ends with ] (right bracket). 

3) 程式Demo

   1. 在MyEclipse中新建Java專案,為了保持對JSON資料處理模組的獨立性,我們可以將下載好的json包放置在獨立的包中,這裡我放置在org.json包中,如下圖所示:

  

   2. 下面程式碼是對Json進行一些物件與字串之間轉換的簡單操作。Test.java

package com.ahuier.json;

import org.json.JSONArray;
import org.json.JSONObject;

public class Test {

    public static void main(String[] args) throws Exception {

        // 相當於客戶端給我們服務端傳過來的JSON資料,它裡面有兩個名值對。
        String jsonContent = "{'hello':'world', 'abc':'xyz'}";

        // 這裡面有一個異常,因為有可能你傳遞過來的不是一個合法的JSON資料格式。
        JSONObject jsonObject = new JSONObject(jsonContent);

        // jsonObject.getXXX() 之所以有這麼多的get方法主要是因為傳遞過來的JSon值的型別可能有很多不一樣的
        String str1 = jsonObject.getString("hello");
        String str2 = jsonObject.getString("abc");

        System.out.println(str1);
        System.out.println(str2);

        // 下面處理陣列
        System.out.println("----------------------------------");
        jsonContent = "[{'AHuier':'XIAMEN', 'age':30, 'flag':false}, " +
        		"{'AHuier':'BEIJING', 'age':24, 'flag':true}]";

        // 既然是陣列,JSONArray裡面肯定提供運算元組的方法。
        JSONArray jsonArray = new JSONArray(jsonContent);

        // 所以我們需要遍歷這個陣列,用getJSONObject()方法,返回JSONObject物件
        // 這樣我們就可以類似上例中通過JSONObject物件取出相應的值.
        for (int i = 0; i < jsonArray.length(); i++) {
            JSONObject jsonObject2 = jsonArray.getJSONObject(i);
            String str = jsonObject2.getString("AHuier");
            int value = jsonObject2.getInt("age");
            boolean flag = jsonObject2.getBoolean("flag");
            System.out.println(str + " " + value + " " + flag);
        }
    }
}

程式執行結果:

world
xyz
----------------------------------
XIAMEN 30 false
BEIJING 24 true

[注意]:上述程式陣列這塊程式碼段進行修改,在陣列中的一個物件元素中再嵌入物件,則遍歷方式需要改變如下所示:

        // 下面處理陣列
        System.out.println("----------------------------------");
        jsonContent = "[{'AHuier':'XIAMEN', 'age':30, 'flag':false, 'add':{'a':1, 'b':'ab'}}, " +
        		"{'AHuier':'BEIJING', 'age':24, 'flag':true, 'add':{'a':3, 'b':'ba'}}]";

        // 既然是陣列,JSONArray裡面肯定提供運算元組的方法。
        JSONArray jsonArray = new JSONArray(jsonContent);

        // 所以我們需要遍歷這個陣列,用getJSONObject()方法,返回JSONObject物件
        // 這樣我們就可以類似上例中通過JSONObject物件取出相應的值.
        for (int i = 0; i < jsonArray.length(); i++) {
            JSONObject jsonObject2 = jsonArray.getJSONObject(i);
            String str = jsonObject2.getString("AHuier");
            int value = jsonObject2.getInt("age");
            boolean flag = jsonObject2.getBoolean("flag");
            
            JSONObject jsonObject3 = jsonObject2.getJSONObject("add");
            int value2 = jsonObject3.getInt("a");
            String str3 = jsonObject3.getString("b"); 
            System.out.println(str + " " + value + " " + flag);
            System.out.println(value2 + str3);
程式執行結果:

world
xyz
----------------------------------
XIAMEN 30 false
1ab
BEIJING 24 true
3ba

5. 中Java專案的JSON開源庫我們一般使用的是 org.json | google-gson | Json-lib 等這幾個專案,在後面的內容中我們都會使用到這些優秀的JSON開源專案,讀者可以自己去讀專案介紹。

   org.json 專案存放的路徑是在GitHub
   gson 存放的是託管在code.google
   JSON-lib 存放是託管在 sourceforge

  現在我們已經知道JSON資料格式的基本知識,下一講我們需要學習一下GSON的資料格式,然後重點學習一下JSON資料格式在Android客戶端與服務端之間的資料互動。