zoukankan      html  css  js  c++  java
  • Android网络之数据解析----使用Google Gson解析Json数据

    【声明】 

    欢迎转载,但请保留文章原始出处→_→ 

    生命壹号:http://www.cnblogs.com/smyhvae/

    文章来源:http://www.cnblogs.com/smyhvae/p/4063452.html

     

    【正文】

    文章回顾: Android网络之数据解析----SAX方式解析XML数据

    一、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.14webappsROOT目录中新建文件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"/> 

    程序运行在模拟器上运行后,界面如下:

    5568d68e-7a46-4414-973b-40024f1f39c2

    分别点击这两个按钮,后台打印的日志如下:

    abc4a572-4423-4ceb-afd7-700839babf93

    在真机上运行的效果如下:

    f420ae51-991c-4d9c-8c5b-ba096eb3c05b

    说明Json数据解析成功,大功告成。

    最后声明:

    其实,如果是在模拟器上运行,即使不添加网络权限,也是没有关系的;但是,如果在真机上运行(前提是真机和电脑在同一个局域网),不添加网络权限,程序是绝对运行不了的,点击按钮,程序就会死掉,这个地方又耽误了我半个小时,罪过。

    【工程文件】

    链接:http://pan.baidu.com/s/1mgj0FY4

    密码:61u3

  • 相关阅读:
    (四)自定义多个Realm以及Authenticator与AuthenticationStrategy
    (三)自定义Realm
    (二)shiro之jsp标签
    (一)shiro简介和用户登录demo及角色管理
    解决Cannot change version of project facet Dynamic web module to 2.5(转)
    (十二)easyUI之表单和验证完成登录页面
    (十一)springmvc和spring的整合
    (十)springmvc之文件的处理
    (九)springmvc之json的数据请求(客户端发送json数据到服务端)
    (九)springmvc之json的处理(服务端发送json数据到客户端)
  • 原文地址:https://www.cnblogs.com/qianguyihao/p/4063452.html
Copyright © 2011-2022 走看看