Android網絡之數據解析—-使用Google Gson解析Json數據

一、Json數據的介紹                                                                                                                

 

Json(JavaScript Object Notation) 是一種輕量級的數據交換格式。它基於JS的一個子集。 Json采用完全獨立於語言的文本格式,這使得Json成為理想的數據交換語言。易於人閱讀和編寫,同時也易於機器解析和生成。

 

Json簡單來說就是JS中的對象和數組,所以Json也存在兩種結構:對象、數組。

 

1、Json對象:

 

含義:是“‘鍵/值’對”的無序集合

 

格式:Json對象定義在花括號“{}”內,以Key:value鍵值對的形式存放數據,多個鍵值對之間使用逗號“,”隔開,多個數據使用分號“;”隔開。

 

 

 

舉例:

 

{

    “name”:”jackson”,

    “age”:100

}

註:不同的語言中,它被理解為對象(object)、紀錄(record)、結構(struct)、字典(dictionary)、哈希表(hash table)、有鍵列表(keyed list)、或者關聯數組 (associative array)。

 

2、Json數組:

 

含義:數組是值(value)的有序集合

 

格式:Json數組定義在方括號“[]”內,以字符串的形式存放數據,值之間使用逗號“,”隔開,多個數據使用分號“;”隔開。

 

 

 

舉例:

 

復制代碼

1 {

2     “students”:

3     [

4         {“name”:”jackson”,“age”:100},

5         {“name”:”michael”,”age”:51}

6     ]

7 }

復制代碼

一般情況下,我們用jsp+servlet作服務器端,生成Json的數據;然後在客戶端解析Json的數據。

 

解析JSON數據, 首先需要明確待解析的是JSON Object還是JSON array, 然後需要確定采用哪種解析技術。android平臺上一般有以下幾種解析技術可供選擇:android內置的org.json包(Json),google的開源庫GSON,還有一些第三方的開源庫如Jackson、FastJson等。我們今天來學習一下使用開源庫GSON來解析Json數據。

 

 

 

二、Gson解析Json的基本思路                                                                                                     

 

首先在服務器端,將服務器端的Person對象通過Gson解析成json的字符串;然後在客戶端,通過Gson類將json的字符串還原為Person對象。Gson支持任意復雜Java對象包括沒有源代碼的對象。

 

如果我們將Person對象看成一個泛型,那麼不管服務器端的Person對象是什麼類型,都可以解析出來。

 

Gson庫神奇在哪裡呢?如果解析的是Json對象,它主要就是可以將一段Json格式的字符串自動映射成一個對象,從而不需要我們再手動去編寫代碼進行解析瞭。比如一段Json格式的數據如下:

 

{"name":"tom","age":20} 

那我們就可以寫一個Person類,並加入name和age這兩個字段,隻需要簡單地調用如下代碼就可以將Json數據自動解析成一個Person對象瞭:

 

Gson gson = new Gson();

 

Person person = gson.fromJson(jsonData,Person.class); 

如果解析的是Json對象數組,就要麻煩一點,需要借助Typetoken(官方提供的一種反射機制)將期望解析成的數據類型傳入到fromJson()方法中,如下所示:

 

List<Person> people = gson.fromJson(jsonData, new TypeToken<List<Person>>().getType()); 

基本用法就是這樣,我們現在來看一下具體的實現步驟吧。

 

 

 

三、Gson解析Json的步驟(代碼實現)                                                                                           

 

現在通過一個示例程序來講解一下SAX是怎麼解析XML文件的,這個示例程序是運行在Android平臺上的,為瞭模擬真實情況,在tomcat服務器上放置瞭一個兩個靜態的XML文件:person.json和perons.json,前者代表對象,後者代表對象數組。即在D:\apache-tomcat-8.0.14\webapps\ROOT目錄中新建文件person.json和perons.json.

 

person.json的內容如下:

 

{

"id": 1,

"name": "smyhvae",

"address":"成都"

需要特別註意的是,要註意json文件的格式。例如第4行的後面不要有逗號(我就是因為這個低級錯誤,導致後來調試程序,調瞭半個多小時才發覺)

 

persons.json的內容如下:

 

復制代碼

[{

    "id": 1,

    "name": "smyhvae",

    "address":"成都"

},

{

    "id": 2,

    "name": "許嵩",

    "address":"合肥"

}] 

復制代碼

註:關於tomcat服務器的配置,如果不清楚的話,請參照本人另外一篇博客的第三段:JavaWeb學習(一)—-JSP簡介及入門(含Tomcat的使用)

 

因為我電腦的IP地址是192.168.1.112。現在我們在瀏覽器輸入http://192.168.1.112:8080/person.json和http://192.168.1.112:8080/persons.json,顯示效果如下:

 

62c20a5a-d379-46f8-bd1c-daf38c4e4769

 

6d9e0f81-9f9f-4360-a71f-7f0193a49b02

 

上方的中文出現瞭亂碼,不過沒關系,在稍後解析的時候是不會出現這種情況的。

 

現在我們需要做的是:通過Android程序去獲取並解析這段Json數據。因為是Android程序,所以別忘瞭賦予其訪問網絡的權限。

 

整個工程文件的目錄結構如下:

 

e51039d5-853b-416f-b73f-05658ead3455

 

(1)下載並添加Gson的jar包:

 

下載地址:https://code.google.com/p/google-gson/  網頁界面如下:

 

812a5333-9666-4300-ac76-e13c5a0692fe

 

點擊上圖中的紅框部分,出現如下界面:

 

83df9ed0-fde0-45cb-9119-01a5682afe3d

 

上圖中的紅框部分gson-2.3.jar就是我們需要下載的內容,如果需要幫助文檔的話,也可以把箭頭處的文件下載下來。然後把gson-2.3.jar拷貝到工程文件的libs目錄下,Gson庫就自動添加到項目中去瞭。

 

(2)【新建工具類HttpUtils】通過URLHttpConnection獲取服務器上的XML流:返回的是字符串

 

復制代碼

 1 package com.example.android_gson_json.http;

 2 

 3 import java.io.ByteArrayOutputStream;

 4 import java.io.IOException;

 5 import java.io.InputStream;

 6 import java.net.HttpURLConnection;

 7 import java.net.URL;

 8 

 9 

10 //通過HttpURLCnnection獲取鏈接裡的數據,放到流裡,然後把流裡面的數據轉換為字符串(借鑒於:老羅老版本1-04)

11 public class HttpUtils {

12 

13     public HttpUtils() {

14         // TODO Auto-generated constructor stub

15     }

16 

17     public static String getJsonContent(String url_path) {

18         try {

19             URL url = new URL(url_path);

20             HttpURLConnection connection = (HttpURLConnection) url

21                     .openConnection();

22             connection.setConnectTimeout(3000);

23             connection.setRequestMethod("GET");

24             connection.setDoInput(true);

25             int code = connection.getResponseCode();

26             if (code == 200) {

27                 return changeInputStream(connection.getInputStream());

28             }

29         } catch (Exception e) {

30             // TODO: handle exception

31         }

32         return "";

33     }

34 

35     private static String changeInputStream(InputStream inputStream) {

36         // TODO Auto-generated method stub

37         String jsonString = "";

38         ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

39         int len = 0;

40         byte[] data = new byte[1024];

41         try {

42             while ((len = inputStream.read(data)) != -1) {

43                 outputStream.write(data, 0, len);

44             }

45             jsonString = new String(outputStream.toByteArray());

46         } catch (IOException e) {

47             // TODO Auto-generated catch block

48             e.printStackTrace();

49         }

50         return jsonString;

51     }

52 }

復制代碼

(3)【新建類Person】新建實體類Person,用於存放解析完成後的對象數據

 

復制代碼

 1 package com.example.android_gson_json.domain;

 2 

 3 public class Person {

 4     private int id;

 5     private String name;

 6     private String address;

 7     public Person() {

 8         super();

 9     }

10     public Person(int id, String name, String address) {

11         super();

12         this.id = id;

13         this.name = name;

14         this.address = address;

15     }

16     public int getId() {

17         return id;

18     }

19     public void setId(int id) {

20         this.id = id;

21     }

22     public String getName() {

23         return name;

24     }

25     public void setName(String name) {

26         this.name = name;

27     }

28     public String getAddress() {

29         return address;

30     }

31     public void setAddress(String address) {

32         this.address = address;

33     }

34     @Override

35     public String toString() {

36         return "Person [id=" + id + ", name=" + name + ", address=" + address

37                 + "]";

38     }    

39     

40 }

復制代碼

(4)【新建類GsonTools】真正用於解析Json數據

 

復制代碼

 1 package com.example.android_gson_json.gson;

 2 

 3 import java.util.ArrayList;

 4 import java.util.List;

 5 

 6 import com.google.gson.Gson;

 7 import com.google.gson.reflect.TypeToken;

 8 

 9 public class GsonTools {

10 

11     public GsonTools() {

12         // TODO Auto-generated constructor stub

13     }

14 

15     //使用Gson進行解析Person

16     public static <T> T getPerson(String jsonString, Class<T> cls) {

17         T t = null;

18         try {

19             Gson gson = new Gson();

20             t = gson.fromJson(jsonString, cls);

21         } catch (Exception e) {

22             // TODO: handle exception

23         }

24         return t;

25     }

26     

27     

28     // 使用Gson進行解析 List<Person>

29     public static <T> List<T> getPersons(String jsonString, Class<T> cls) {

30         List<T> list = new ArrayList<T>();

31         try {

32             Gson gson = new Gson();

33             list = gson.fromJson(jsonString, new TypeToken<List<T>>() {

34             }.getType());

35         } catch (Exception e) {

36         }

37         return list;

38     }

39 

40 }

復制代碼

上面有兩個方法,分別用於解析Person對象、List嵌套的Person。如果還有更復雜的數據類型,以後再說吧~O(∩_∩)O~這裡隻需要註意關鍵的思路就行。

 

核心代碼:19至20行、32至34行

 

(5)在MainActicity中實例化:即實例化需要訪問的鏈接path並解析它

 

佈局界面很簡單,隻有兩個按鈕控件,這裡就不展示佈局代碼瞭。點擊按鈕後,觸發點擊事件,因為是Android4.0+,所以不能在主線程中訪問網絡,需要另起一個線程,這裡使用Thread類。代碼如下: 

 

復制代碼

 1 package com.example.android_gson_json;

 2 

 3 import java.util.List;

 4 

 5 import android.app.Activity;

 6 import android.os.Bundle;

 7 import android.util.Log;

 8 import android.view.View;

 9 import android.view.View.OnClickListener;

10 import android.widget.Button;

11 

12 import com.example.android_gson_json.domain.Person;

13 import com.example.android_gson_json.gson.GsonTools;

14 import com.example.android_gson_json.http.HttpUtils;

15 

16 public class MainActivity extends Activity implements OnClickListener {

17 

18     private Button button1, button2;

19     private static final String TAG = "MainActivity";

20 

21     @Override

22     protected void onCreate(Bundle savedInstanceState) {

23         super.onCreate(savedInstanceState);

24         setContentView(R.layout.activity_main);

25 

26         button1 = (Button) this.findViewById(R.id.button1);

27         button2 = (Button) this.findViewById(R.id.button2);

28         button1.setOnClickListener(this);

29         button2.setOnClickListener(this);

30     }

31 

32     //點擊按鈕,開始使用Gson解析Json數據:Person對象、List嵌套的Person對象的集合

33     @Override

34     public void onClick(final View v) {

35         Thread thread = new Thread(new Runnable() {

36 

37             @Override

38             public void run() {

39                 switch (v.getId()) {

40                 case R.id.button1:

41                     String path = "http://192.168.1.112:8080/person.json";

42                     String jsonString = HttpUtils.getJsonContent(path);//從網絡獲取數據

43                     Person person = GsonTools.getPerson(jsonString, Person.class);//解析json數據

44                     Log.i(TAG, person.toString());

45                     break;

46                 case R.id.button2:

47                     String path2 = "http://192.168.1.112:8080/persons.json";

48                     String jsonString2 = HttpUtils.getJsonContent(path2);//從網絡獲取數據

49                     List<Person> list = GsonTools.getPersons(jsonString2, Person.class);//解析json數據

50                     Log.i(TAG, list.toString());

51                     break;

52                 }

53 

54             }

55         });

56         thread.start();

57 

58     }

59 

60 }

復制代碼

核心代碼:43行、49行

 

(6)添加網絡權限:(這個千萬不要忘記瞭)

 

<uses-sdk

android:minSdkVersion="14"

android:targetSdkVersion="21" />

<uses-permission android:name="android.permission.INTERNET"/> 

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。