前面我们已经掌握了xml格式数据的解析方式,那么接下来我们学习下如何解析json格式的数据。比起xml,json的主要优势在于它体积更小,在网络上传输的时候可以更省流量。但缺点在于,它的语义性差,看起来不如xml直观。
开始之前,先在自己的电脑apache-tomcat-6.0.39\webapps\ROOT路径目录下新建一个get_data.json的文件,然后编辑这个文件,并加入如下json格式的内容:
[{"id":"5","version":"5.5","name":"angelababy"},
{"id":"6","version":"7.0","name":"clash of clans"},
{"id":"7","version":"3.5","name":"hey day"}]
这时候在浏览器访问的结果如下:
这样就把json格式的数据准备好了,下面我们在android程序中解析这些数据吧。
使用JSONObject解析json格式的数据
解析json格式的数据有很多种方式,可以使用官方提供的JSONObject,也可以用谷歌的开源库GSON。
还有一些第三方的开源库,比如Jackson,FastSON等。目前只讲解JSONObject和GSON。
修改MainActivity中的代码,如下所示:
package com.jack.networktest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import javax.xml.parsers.SAXParserFactory;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONObject;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity implements OnClickListener{
public static final int SHOW_RESPONSE=0;
private Button sendRequest=null;
private TextView responseText=null;
private Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
switch(msg.what){
case SHOW_RESPONSE:
String response=(String) msg.obj;
//在这里进行UI操作,将结果显示到界面上
responseText.setText(response);
break;
default:
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sendRequest=(Button) findViewById(R.id.send_request);
responseText=(TextView) findViewById(R.id.response_text);
sendRequest.setOnClickListener(this);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(v.getId()==R.id.send_request){
//sendRequestWithHttpURLConnection();
sendRequestWithHttpClient();
}
}
private void sendRequestWithHttpURLConnection(){
//开启线程来发起网络请求
new Thread(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
HttpURLConnection connection=null;
try {
URL url=new URL("http://www.baidu.com");
connection =(HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(8000);
connection.setReadTimeout(8000);
InputStream in=connection.getInputStream();
//下面对获取到的输入流进行读取
BufferedReader reader=new BufferedReader(new InputStreamReader(in));
StringBuilder response=new StringBuilder();
String line;
while((line=reader.readLine())!=null){
response.append(line);
}
Message message=new Message();
message.what=SHOW_RESPONSE;
//将服务器返回的结果存放到Message中
message.obj=response.toString();
handler.sendMessage(message);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}catch(Exception e){
e.printStackTrace();
}finally{
if(connection!=null){
connection.disconnect();
}
}
}
}).start();
}
private void sendRequestWithHttpClient(){
new Thread(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
try{
HttpClient httpClient=new DefaultHttpClient() ;
//HttpGet httpGet=new HttpGet("http://www.baidu.com");
//指定访问的服务器地址是电脑本机,10.0.2.2对模拟器来说就是电脑本机的ip地址
//8080为端口号
//HttpGet httpGet=new HttpGet("http://10.0.2.2:8080/get_data.xml");
HttpGet httpGet=new HttpGet("http://10.0.2.2:8080/get_data.json");
HttpResponse httpResponse=httpClient.execute(httpGet);
if(httpResponse.getStatusLine().getStatusCode()==200){
//请求和响应都成功了
HttpEntity entity=httpResponse.getEntity();
String response=EntityUtils.toString(entity,"utf-8");
//调用parseXMLWithPull方法解析服务器返回的数据
//parseXMLWithPull(response);
//调用parseXMLWithSAX方法解析服务器返回的数据
parseXMLWithSAX(response);
//调用parseJSONWithJSONObject方法解析服务器返回的数据
parseJSONWithJSONObject(response);
Message message=new Message();
message.what=SHOW_RESPONSE;
//将服务器返回的结果存放到Message中
message.obj=response.toString();
handler.sendMessage(message);
}
}catch(Exception e){
e.printStackTrace();
}
}
}).start();
}
//使用Pull解析xml
private void parseXMLWithPull(String xmlData){
//Log.d("MainActivity", "parseXMLWithPull(String xmlData)");
try{
//获取到XmlPullParserFactory的实例,并借助这个实例得到XmlPullParser对象
XmlPullParserFactory factory=XmlPullParserFactory.newInstance();
XmlPullParser xmlPullParser=factory.newPullParser();
//调用XmlPullParser的setInput方法将服务器返回的xml数据设置进去开始解析
xmlPullParser.setInput(new StringReader(xmlData));
//通过getEventType()方法得到当前解析事件
int eventType=xmlPullParser.getEventType();
String id="";
String name="";
String version="";
while(eventType!=XmlPullParser.END_DOCUMENT){
//通过getName()方法得到当前节点的名字,如果发现节点名等于id、name、或version
//就调用nextText()方法来获取结点具体的内容,每当解析完一个app结点就将获取到的内容打印出来
String nodeName=xmlPullParser.getName();
//Log.d("MainActivity",""+eventType+ " nodeName= "+nodeName);
switch(eventType){
//开始解析某个节点
case XmlPullParser.START_TAG:{
if("id".equals(nodeName)){
id=xmlPullParser.nextText();
}else if("name".equals(nodeName)){
name=xmlPullParser.nextText();
}else if("version".equals(nodeName)){
version=xmlPullParser.nextText();
}
break;
}
case XmlPullParser.END_TAG:{
if("app".equals(nodeName)){
Log.d("MainActivity", "id is "+id);
Log.d("MainActivity", "name is "+name);
Log.d("MainActivity", "version is "+version);
}
break;
}
default:
break;
}
//调用next()方法获取到下一个解析事件
eventType=xmlPullParser.next();
}
}catch(Exception e){
e.printStackTrace();
}
}
//进行SAX解析的函数
private void parseXMLWithSAX(String xmlData){
/*
* parseXMLWithSAX方法中先创建一个SAXParserFactory的对象,然后再获取到
* XMLReader对象,接着将我们编写的ContentHandler的实例设置到XMLReader中,
* 最后调用parse()方法开始执行解析。
* */
try{
SAXParserFactory factory=SAXParserFactory.newInstance();
XMLReader xmlReader=factory.newSAXParser().getXMLReader();
ContentHandler handler=new ContentHandler();
//将ContentHandler的实例设置到XMLReader中
xmlReader.setContentHandler(handler);
//开始执行解析
xmlReader.parse(new InputSource(new StringReader(xmlData)));
}catch(Exception e){
e.printStackTrace();
}
}
//使用JSONObject解析json格式的数据
private void parseJSONWithJSONObject(String jsonData){
/*
* 首先把http请求的地址改成http://localhost:8080/get_data.json,然后在得到服务器返回
* 的数据后调用parseJSONWithJSONObject()方法来解析数据。由于我们在服务器中定义的是一个json数组,
* 因此解析的时候首先是将服务器返回的数据传入到一个JSONArray对象中。然后循环遍历这个JSONArray,从
* 中取出的每一个元素都是一个JSONObject对象,每个JSONObject对象中又包含了id,name和version这些
* 数据。接下来只需要调用getString()方法将这些数据取出,并打印出来即可。
* */
try{
JSONArray jsonArray=new JSONArray(jsonData);
for(int i=0;i<jsonArray.length();i++){
JSONObject jsonObject=jsonArray.getJSONObject(i);
String id=jsonObject.getString("id");
String name=jsonObject.getString("name");
String version=jsonObject.getString("version");
Log.d("MainActivity", "id is "+id);
Log.d("MainActivity", "name is "+name);
Log.d("MainActivity", "version is "+version);
}
}catch(Exception e){
e.printStackTrace();
}
}
}
现在重新运行下程序,点击send request按钮,结果如下所示:
使用GSON
谷歌提供的GSON开源库可以让解析JSON数据的工作简单到不敢想象的地步。要使用GSON必须要在项目中添加一个 GSON的jar包。首先需要将GSON的资源压缩包下载下来,下载地址是:htt://code.google.com/p/google-gson/downloads/list
然后把下载下来的gson-x.x.x.jar包拷贝到NetworkTest项目的libs目录下,GSON库就自动添加到项目了。
GSON的强大之处,在于可以将一段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());
好了,基本的用法就是这样了,下面我们来试试,首先新增一个App类,并加入id,name和version这三个字段,如下所示:
package com.jack.networktest;
public class App {
private String id;
private String name;
private String version;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
}
然后修改MainActivity中的代码,如下所示:
package com.jack.networktest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import javax.xml.parsers.SAXParserFactory;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONObject;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity implements OnClickListener{
public static final int SHOW_RESPONSE=0;
private Button sendRequest=null;
private TextView responseText=null;
private Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
switch(msg.what){
case SHOW_RESPONSE:
String response=(String) msg.obj;
//在这里进行UI操作,将结果显示到界面上
responseText.setText(response);
break;
default:
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sendRequest=(Button) findViewById(R.id.send_request);
responseText=(TextView) findViewById(R.id.response_text);
sendRequest.setOnClickListener(this);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(v.getId()==R.id.send_request){
//sendRequestWithHttpURLConnection();
sendRequestWithHttpClient();
}
}
private void sendRequestWithHttpURLConnection(){
//开启线程来发起网络请求
new Thread(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
HttpURLConnection connection=null;
try {
URL url=new URL("http://www.baidu.com");
connection =(HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(8000);
connection.setReadTimeout(8000);
InputStream in=connection.getInputStream();
//下面对获取到的输入流进行读取
BufferedReader reader=new BufferedReader(new InputStreamReader(in));
StringBuilder response=new StringBuilder();
String line;
while((line=reader.readLine())!=null){
response.append(line);
}
Message message=new Message();
message.what=SHOW_RESPONSE;
//将服务器返回的结果存放到Message中
message.obj=response.toString();
handler.sendMessage(message);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}catch(Exception e){
e.printStackTrace();
}finally{
if(connection!=null){
connection.disconnect();
}
}
}
}).start();
}
private void sendRequestWithHttpClient(){
new Thread(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
try{
HttpClient httpClient=new DefaultHttpClient() ;
//HttpGet httpGet=new HttpGet("http://www.baidu.com");
//指定访问的服务器地址是电脑本机,10.0.2.2对模拟器来说就是电脑本机的ip地址
//8080为端口号
//HttpGet httpGet=new HttpGet("http://10.0.2.2:8080/get_data.xml");
HttpGet httpGet=new HttpGet("http://10.0.2.2:8080/get_data.json");
HttpResponse httpResponse=httpClient.execute(httpGet);
if(httpResponse.getStatusLine().getStatusCode()==200){
//请求和响应都成功了
HttpEntity entity=httpResponse.getEntity();
String response=EntityUtils.toString(entity,"utf-8");
//调用parseXMLWithPull方法解析服务器返回的数据
//parseXMLWithPull(response);
//调用parseXMLWithSAX方法解析服务器返回的数据
//parseXMLWithSAX(response);
//调用parseJSONWithJSONObject方法解析服务器返回的数据
//parseJSONWithJSONObject(response);
//调用parseJSONWithGSON方法解析服务器返回的数据
parseJSONWithGSON(response);
Message message=new Message();
message.what=SHOW_RESPONSE;
//将服务器返回的结果存放到Message中
message.obj=response.toString();
handler.sendMessage(message);
}
}catch(Exception e){
e.printStackTrace();
}
}
}).start();
}
//使用Pull解析xml
private void parseXMLWithPull(String xmlData){
//Log.d("MainActivity", "parseXMLWithPull(String xmlData)");
try{
//获取到XmlPullParserFactory的实例,并借助这个实例得到XmlPullParser对象
XmlPullParserFactory factory=XmlPullParserFactory.newInstance();
XmlPullParser xmlPullParser=factory.newPullParser();
//调用XmlPullParser的setInput方法将服务器返回的xml数据设置进去开始解析
xmlPullParser.setInput(new StringReader(xmlData));
//通过getEventType()方法得到当前解析事件
int eventType=xmlPullParser.getEventType();
String id="";
String name="";
String version="";
while(eventType!=XmlPullParser.END_DOCUMENT){
//通过getName()方法得到当前节点的名字,如果发现节点名等于id、name、或version
//就调用nextText()方法来获取结点具体的内容,每当解析完一个app结点就将获取到的内容打印出来
String nodeName=xmlPullParser.getName();
//Log.d("MainActivity",""+eventType+ " nodeName= "+nodeName);
switch(eventType){
//开始解析某个节点
case XmlPullParser.START_TAG:{
if("id".equals(nodeName)){
id=xmlPullParser.nextText();
}else if("name".equals(nodeName)){
name=xmlPullParser.nextText();
}else if("version".equals(nodeName)){
version=xmlPullParser.nextText();
}
break;
}
case XmlPullParser.END_TAG:{
if("app".equals(nodeName)){
Log.d("MainActivity", "id is "+id);
Log.d("MainActivity", "name is "+name);
Log.d("MainActivity", "version is "+version);
}
break;
}
default:
break;
}
//调用next()方法获取到下一个解析事件
eventType=xmlPullParser.next();
}
}catch(Exception e){
e.printStackTrace();
}
}
//进行SAX解析的函数
private void parseXMLWithSAX(String xmlData){
/*
* parseXMLWithSAX方法中先创建一个SAXParserFactory的对象,然后再获取到
* XMLReader对象,接着将我们编写的ContentHandler的实例设置到XMLReader中,
* 最后调用parse()方法开始执行解析。
* */
try{
SAXParserFactory factory=SAXParserFactory.newInstance();
XMLReader xmlReader=factory.newSAXParser().getXMLReader();
ContentHandler handler=new ContentHandler();
//将ContentHandler的实例设置到XMLReader中
xmlReader.setContentHandler(handler);
//开始执行解析
xmlReader.parse(new InputSource(new StringReader(xmlData)));
}catch(Exception e){
e.printStackTrace();
}
}
//使用JSONObject解析json格式的数据
private void parseJSONWithJSONObject(String jsonData){
/*
* 首先把http请求的地址改成http://localhost:8080/get_data.json,然后在得到服务器返回
* 的数据后调用parseJSONWithJSONObject()方法来解析数据。由于我们在服务器中定义的是一个json数组,
* 因此解析的时候首先是将服务器返回的数据传入到一个JSONArray对象中。然后循环遍历这个JSONArray,从
* 中取出的每一个元素都是一个JSONObject对象,每个JSONObject对象中又包含了id,name和version这些
* 数据。接下来只需要调用getString()方法将这些数据取出,并打印出来即可。
* */
try{
JSONArray jsonArray=new JSONArray(jsonData);
for(int i=0;i<jsonArray.length();i++){
JSONObject jsonObject=jsonArray.getJSONObject(i);
String id=jsonObject.getString("id");
String name=jsonObject.getString("name");
String version=jsonObject.getString("version");
Log.d("MainActivity", "id is "+id);
Log.d("MainActivity", "name is "+name);
Log.d("MainActivity", "version is "+version);
}
}catch(Exception e){
e.printStackTrace();
}
}
//使用JSONWithGSON(String jsonData)方法解析json格式的数据
private void parseJSONWithGSON(String jsonData){
Gson gson=new Gson();
List<App> appList=gson.fromJson(jsonData, new
TypeToken<List<App>>() {}.getType());
for(App app: appList){
Log.d("MainActivity", "id is "+app.getId());
Log.d("MainActivity", "name is "+app.getName());
Log.d("MainActivity", "version is "+app.getVersion());
}
}
}
运行程序,结果如下所示:
经过上面两种方法对json格式的数据进行解析,相信对json格式的数据应该不再陌生了。
http://blog.csdn.net/j903829182/article/details/42503583