首页 > 代码库 > android学习二十三(解析json格式数据)

android学习二十三(解析json格式数据)

        前面我们已经掌握了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






android学习二十三(解析json格式数据)