經過Gson解析Json數據

Json是一種數據格式,便於數據傳輸、存儲、交換;
Gson是一種組件庫,能夠把java對象數據轉換成json數據格式。html

gson.jar的下載地址:http://search.maven.org/#search%7Cga%7C1%7Ca%3A%22gson%22java

 

1、Json數據樣式android

爲了便於理解咱們先來看看Json的數據樣式:web

1. 單個數據對象json

{
    "id": 100,
    "body": "It is my post",
    "number": 0.13,
    "created_at": "2014-05-22 19:12:38"
}

 

2. 多組數據數組

這是一組Json數據,能夠看到就像數組同樣,一組數據是用[]圍起來的,內部{}圍起來的就是單個的數據對象maven

[{
    "id": 100,
    "body": "It is my post1",
    "number": 0.13,
    "created_at": "2014-05-20 19:12:38"
},
{
    "id": 101,
    "body": "It is my post2",
    "number": 0.14,
    "created_at": "2014-05-22 19:12:38"
}]

 

3. 嵌套數據函數

這段數據是用{}圍起來的因此是單個數據對象,咱們又能發現其內部又是一個數據對象,名字叫foo2.這就是嵌套的Json數據post

{
    "id": 100,
    "body": "It is my post",
    "number": 0.13,
    "created_at": "2014-05-22 19:12:38",
    "foo2": {
        "id": 200,
        "name": "haha"
    }
}

 

2、經過JsonReader解析Json數據ui

2.1 數據

String jsonData = "[{\"username\":\"name01\",\"userId\":001},{\"username\":\"name02\",\"userId\":002}]";

通常的Json都是從網上獲取的,這裏爲了簡單將Json數據直接用String定義。由於該數據中有各類標點符號,因此要用轉譯。

 

2.2 解析

    /**
     * @description 經過JsonReader解析Json對象
     * 
     * @web http://codego.net/480737/
     */
    private void jsonReaderTest() {
        // 這裏的Json放到string中,因此加上了轉譯
        String jsonData = "[{\"username\":\"name01\",\"userId\":001},{\"username\":\"name02\",\"userId\":002}]";

        JsonReader reader = new JsonReader(new StringReader(jsonData));
        reader.setLenient(true); // 在寬鬆模式下解析
        try {
            reader.beginArray(); // 開始解析數組(包含一個或多個Json對象)
            while (reader.hasNext()) { // 若是有下一個數據就繼續解析
                reader.beginObject(); // 開始解析一個新的對象
                while (reader.hasNext()) {
                    String tagName = reader.nextName(); // 獲得下一個屬性名
                    if (tagName.equals("username")) {
                        System.out.println(reader.nextString());
                    } else if (tagName.equals("userId")) {
                        System.out.println(reader.nextString());
                    }
                }
                reader.endObject(); // 結束對象的解析
            }
            reader.endArray(); // 結束解析當前數組
        } catch (IOException e) {
            // TODO 自動生成的 catch 塊
            e.printStackTrace();
        }
    }

在JsonReader的構造函數中傳入json data,而後開始解析,判斷是否還有下一個對象,若是有就開始解析對象名和對象體,直到解析完畢。

 

 3、經過Gson解析單個Json對象

 3.1 數據

assets/Json01

{
    "id": 100,
    "body": "It is my post",
    "number": 0.13,
    "created_at": "2014-05-22 19:12:38"
}

 

3.2 載入數據 

由於這個數據是定義在本地的,因此要先加載到內存中。方法是經過getAssets()獲得AssetManager對象,再經過open(文件名)來得到文件流。這裏由於我能確保本地的文件小於1m,因此就沒作循環讀取,實際中請務必用循環讀取的方式。最終獲得的數據存放在strData中。

  /**
     * @description 經過assets文件獲取json數據,這裏寫的十分簡單,沒作循環判斷。
     *
     * @return Json數據(String)
     */
    private String getStrFromAssets(String name) {
        String strData = null;
        try {
            InputStream inputStream = getAssets().open(name);
            byte buf[] = new byte[1024];
            inputStream.read(buf);
            strData = new String(buf);
            strData = strData.trim();

        } catch (IOException e) {
            // TODO 自動生成的 catch 塊
            e.printStackTrace();
        }
        System.out.println("strData = " + strData);
        return strData;
    }

 

3.3 創建類

首先,咱們要根據數據的格式定義一個類

public class Foo01 {
    public int id;
    public String body;
    public float number;
    public String created_at;
}

這個類的定義方式有講究:

1>類裏面的成員變量名必須跟Json字段裏面的name是如出一轍的:

"id": 100,  ----  public int id;

2>若是Json數據是嵌套定義的,那麼這個類中就的成員變量確定有個類對象,通常這個類包含內部類

{
    "id": 100,
    "body": "It is my post",
    "number": 0.13,
    "created_at": "2014-05-22 19:12:38",
    "childFoo": {
        "id": 200,
        "name": "jack"
    }
}
public class Foo02 {
    private int id;
    private String body;
    private float number;
    
    @SerializedName("created_at")
    private Date createdAt; // 經過註釋的方式更換名字,同時保證使用方式不變。

}

 

3.4 開始解析

    /**
     * @description 將json數據解析爲類對象
     */
    private void GsonTest01() {
        Foo01 foo = new Gson().fromJson(getStrFromAssets("Json01"), Foo01.class);
        System.out.println("id = " + foo.id);
    }

 

3.5 結果

 

4、經過Gson將數據轉換爲Date對象,而且重命名

4.1 數據

本例的數據和上面徹底同樣,是單個的Json數據

{
    "id": 100,
    "body": "It is my post",
    "number": 0.13,
    "created_at": "2014-05-22 19:12:38"
}

咱們能夠明顯的發現,最後的創建日期是一個date對象,但經過通常的解析方式,咱們只能把日期數據賦值給string,但之後的操做就很麻煩了。所以,咱們用到了gsonBuilder。gsonBuilder能夠經過檢查json數據的格式,講符合用戶設置格式的數據變爲相應的對象,下面就來演示一下。

 

4.2 解析

解析仍是兩步,首先定義一個類:

public class Foo02 {
    private int id;
    private String body;
    private float number;
    
    @SerializedName("created_at")
    private Date createdAt; // 經過註釋的方式更換名字,同時保證使用方式不變。
    
    public String get_my_date() {
        return createdAt.toString();
    }
}

 而後,經過gson解析:

    /**
     * @description 當json中有日期對象時,經過定義構建格式生成須要的date對象
     * 當json數據命名和java命名產生不一致時,能夠經過註釋的方式實現更換名字,更方便進行代碼處理
     */
    private void GsonTest02() {
        GsonBuilder gsonBuilder = new GsonBuilder();
        gsonBuilder.setDateFormat("yyyy-MM-dd HH:mm:ss"); // 設置日期的格式,遇到這個格式的數據轉爲Date對象
        Gson gson = gsonBuilder.create();
        Foo02 foo = gson.fromJson(getStrFromAssets("Json01"), Foo02.class);
        System.out.println("date = " + foo.get_my_date());
    }

 

分析:初始化GsonBuilder後,經過setDateFormat來設置什麼樣的數據會變爲date對象,由於原始數據中created_at的日期格式是yyyy-mm-dd HH:mm:ss因此就寫了以下的代碼:

gsonBuilder.setDateFormat("yyyy-MM-dd HH:mm:ss"); // 設置日期的格式,遇到這個格式的數據轉爲Date對象

以後再經過gsonBuilder的create來創建gson對象,而後解析便可。

 

4.3 重命名

有時候json的對象名不符合java命名規則,好比這個created_at就沒采用駝峯命名法,但java代碼中推薦用駝峯命名,這樣就產生了矛盾,雖然能夠用別的方式來解決,但咱們還但願用代碼在不影響解析的狀況下,產生符合java命名規則的成員變量。實現也至關簡單,用註釋。

public class Foo02 {
    private int id;
    private String body;
    private float number;
    
    @SerializedName("created_at")
    private Date createdAt; // 經過註釋的方式更換名字,同時保證使用方式不變。
    
    public String get_my_date() {
        // 能夠經過simpleDateFormat指定data對象的輸出格式,注意:若是要添加自定義字符串,好比下面的custom,必須在字符串兩邊加單引號。
        SimpleDateFormat dateFormat = new SimpleDateFormat("'custom'_yyyyMMdd_HHmmss");
        //return dateFormat.format(created_at);
        
        return createdAt.toString();
    }
}

在創建Date對象時,咱們在上面加上了換名設定,這樣gson解析時會根據created_at來初始化這個date對象,而咱們使用的時候用craetedAt就能夠了。這裏順便提一下,若是你要輸出date,能夠經過simpleDtaeFormat來設置輸出的格式,這點在設置照片名或文件名時頗有用。固然,若是你沒這個需求,你徹底能夠用toString()方法。

 

4.4 結果

能夠看見,這裏的date對象是按照標準的格式進行顯示的,說明解析成功!

 

5、解析嵌套的Json數據

5.1數據

{
    "id": 100,
    "body": "It is my post",
    "number": 0.13,
    "created_at": "2014-05-22 19:12:38",
    "childFoo": {
        "id": 200,
        "name": "jack"
    }
}

先來分析下數據,這是一個單個數據,裏面嵌套了一個childFoo。那麼構建類的時候就須要有兩個類,一個類包含id,body,number,created_at,childFoo.另外一個類中包含id,name。

 

5.2 構建類

這裏爲了簡單,把兩個類合二爲一了。注意下這個內部類其實能夠不叫ChildFoo的,只要這個類產生的對象的名字叫作childFoo就行(區分大小寫)。

package com.kale.gsontest;

/**
 * @author:Jack Tony
 * @description  : 針對有嵌套的json數據
 * @date  :2015年1月24日
 */
public class Foo03 {
    public int id;
    public String body;
    public float number;
    public String created_at;
    public ChildFoo childFoo;

    public class ChildFoo {
        public int id;
        public String name;
    }
}

 

5.3 解析

    /**
     * @description 解析嵌套是Json數據
     *
     */
    private void GsonTest03() {
        Foo03 foo = new Gson().fromJson(getStrFromAssets("Json02"), Foo03.class);
        System.out.println("name = " + foo.childFoo.name);
    }

爲了看是否解析成功,這裏直接輸出類中內部類的成員變量:name

 

5.4 結果

能夠看見,輸出了childFoo中的name值:jack

 

6、將Json序列解析爲數組

6.1 數據

[{
    "id": 100,
    "body": "It is my post1",
    "number": 0.13,
    "created_at": "2014-05-20 19:12:38"
},
{
    "id": 101,
    "body": "It is my post2",
    "number": 0.14,
    "created_at": "2014-05-22 19:12:38"
}]

一般狀況下Json數據包含多個對象,若是不包含多個對象的狀況比較少見。舉個例子:

http://m.weather.com.cn/data/101010100.html

{"weatherinfo":{"city":"北京","city_en":"beijing","date_y":"2014年3月4日","date":"","week":"星期二","fchh":"11","cityid":"101010100","temp1":"8℃~-3℃","temp2":"8℃~-3℃","temp3":"7℃~-3℃","temp4":"8℃~-1℃","temp5":"10℃~1℃","temp6":"10℃~2℃","tempF1":"46.4℉~26.6℉","tempF2":"46.4℉~26.6℉","tempF3":"44.6℉~26.6℉","tempF4":"46.4℉~30.2℉","tempF5":"50℉~33.8℉","tempF6":"50℉~35.6℉","weather1":"晴","weather2":"晴","weather3":"晴","weather4":"晴轉多雲","weather5":"多雲","weather6":"多雲","img1":"0","img2":"99","img3":"0","img4":"99","img5":"0","img6":"99","img7":"0","img8":"1","img9":"1","img10":"99","img11":"1","img12":"99","img_single":"0","img_title1":"晴","img_title2":"晴","img_title3":"晴","img_title4":"晴","img_title5":"晴","img_title6":"晴","img_title7":"晴","img_title8":"多雲","img_title9":"多雲","img_title10":"多雲","img_title11":"多雲","img_title12":"多雲","img_title_single":"晴","wind1":"北風4-5級轉微風","wind2":"微風","wind3":"微風","wind4":"微風","wind5":"微風","wind6":"微風","fx1":"北風","fx2":"微風","fl1":"4-5級轉小於3級","fl2":"小於3級","fl3":"小於3級","fl4":"小於3級","fl5":"小於3級","fl6":"小於3級","index":"寒冷","index_d":"天氣寒冷,建議着厚羽絨服、毛皮大衣加厚毛衣等隆冬服裝。年老體弱者尤爲要注意保暖防凍。","index48":"冷","index48_d":"天氣冷,建議着棉服、羽絨服、皮夾克加羊毛衫等冬季服裝。年老體弱者宜着厚棉衣、冬大衣或厚羽絨服。","index_uv":"中等","index48_uv":"中等","index_xc":"較適宜","index_tr":"通常","index_co":"較溫馨","st1":"7","st2":"-3","st3":"8","st4":"0","st5":"7","st6":"-1","index_cl":"較不宜","index_ls":"基本適宜","index_ag":"易發"}}

如今咱們想把這多個對象解析爲一個數組對象,應該怎麼作呢?

 

6.2 創建類

十分簡單,包含一個對象中的信息便可。順便一提,若是你不須要解析那麼多結果,你能夠僅僅列出你想要解析的變量。

public class Foo01 {
    public int id;
    public String body;
    public float number;
    public String created_at;
}

 

6.3 解析

    /**
     * @description 解析爲數組
     *
     */
    private void GsonTest04() {
        Foo01[] foos = new Gson().fromJson(getStrFromAssets("Json03"), Foo01[].class);
        System.out.println("name01 = " + foos[0].id);
        System.out.println("name02 = " + foos[1].id);
        // 這時候想轉成List的話調用以下方法
        // List<Foo> foosList = Arrays.asList(foos);
    }

gson的構造函數提供瞭解析成數組對象的方法,因此直接像解析單個對象同樣使用就行。

 

6.4 結果

 

7、將數據解析爲list

7.1 數據

這個數據和上面徹底同樣

[{
    "id": 100,
    "body": "It is my post1",
    "number": 0.13,
    "created_at": "2014-05-20 19:12:38"
},
{
    "id": 101,
    "body": "It is my post2",
    "number": 0.14,
    "created_at": "2014-05-22 19:12:38"
}]

 

7.2 創建類

類也和上面的同樣,沒任何變化

package com.kale.gsontest;

public class Foo01 {
    public int id;
    public String body;
    public float number;
    public String created_at;
}

 

7.3 解析

    /**
     * @description 將json序列變爲list對象
     *
     */
    private void GsonTest05() {
        Type listType = new TypeToken<ArrayList<Foo01>>(){}.getType();
ArrayList
<Foo01> foos = new Gson().fromJson(getStrFromAssets("Json03"), listType); for (int i = 0; i < foos.size(); i++) { System.out.println("name ["+ i +"] = " + foos.get(i).id); } }

這裏不一樣的一點就是要定義list的類型,其他的沒什麼可說的。通常咱們都會用這種方式將數據放到list中,不多會用到解析成數組。

 

7.4 結果

 

源碼下載:http://download.csdn.net/detail/shark0017/8393351

 

 

參考自:

http://stormzhang.com/android/2014/05/22/android-gson/

http://www.cnblogs.com/jxgxy/p/3677256.html

http://search.maven.org/#search%7Cga%7C1%7Ca%3A%22gson%22

相關文章
相關標籤/搜索