Android--Json解析
前言
上一篇博客已经介绍了在.Net下如何把对象序列化成Json字符串和Json数据的格式。如果不清楚的朋友可以过去看看:对象转Json序列化。这篇博客就来聊聊在Android平台下如何解析Json数据。
org.json
我们知道,Json有两种格式,键值对和数组,而Android对于Json的支持源于org.json包下的几个类。org.json下一共有四个类,但是经常使用的也就是两个类,分别对应了键值对和数组:JSONObject、JSONArray,弄清楚这两个类,基本上就了解了在Android下解析Json的方式。
对于这两个类的选择使用,其实可以简单的区分,如果是被包括在方括号"[]"内的Json数据,则使用JSONArray对象存放数据。如果是被包括在花括号"{}"内的Json数据,则使用JSONObject对象存放数据。
如上图,对于上面这个Json数据,解析的思路是先使用JSONArray解析Json数组,再遍历这个Json数组,使用JSONObject解析这个Json数组中的每个Json对象。
示例程序
JSONObject、JSONArray提供了一系列getXxx()的方法,获取其内部的值。下面就通过一个例子来讲解一下Android应用程序中解析Json的方法。
这个例子模拟现实情况,访问IIS上一个一般处理程序,通过不同的GET参数,返回不同的Json数据,具体数据的返回情况参见上一篇博客对象转Json序列化。
在此示例中展示解析四种数据的方式:
- Person:{"age":24,"id":20,"name":"slive"}
- List<Person>:[{"age":24,"id":20,"name":"slive"},{"age":34,"id":30,"name":"jack"},{"age":54,"id":40,"name":"damon"}]
- List<string>:["jack","dick","sean"]
- List<Map<String,Object>>:[[{"Key":"id","Value":17},{"Key":"name","Value":"jerry"},{"Key":"age","Value":24}],[{"Key":"id","Value":18},{"Key":"name","Value":"meimei"},{"Key":"age","Value":23}],[{"Key":"id","Value":19},{"Key":"name","Value":"damon"},{"Key":"age","Value":28}]]
从IIS上获取Json数据的方法,在另外一篇博客中有介绍:Http协议。这里方便大家查看:
1 package cn.bgxt.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 import android.util.Log; 9 10 public class HttpUtils { 11 public HttpUtils() { 12 // TODO Auto-generated constructor stub 13 } 14 public static String getJsonContent(String url_path) 15 { 16 try { 17 URL url=new URL(url_path); 18 HttpURLConnection connection=(HttpURLConnection)url.openConnection(); 19 connection.setConnectTimeout(3000); 20 connection.setRequestMethod("GET"); 21 connection.setDoInput(true); 22 int code=connection.getResponseCode(); 23 if(200==code) 24 { 25 return changeJsonString(connection.getInputStream()); 26 } 27 } catch (Exception e) { 28 // TODO: handle exception 29 Log.i("main", e.getMessage()); 30 } 31 return null; 32 } 33 34 private static String changeJsonString(InputStream inputStream) { 35 String jsonString=""; 36 try { 37 ByteArrayOutputStream outputStream=new ByteArrayOutputStream(); 38 int len=0; 39 byte[] data=new byte[1024]; 40 while((len=inputStream.read(data))!=-1) 41 { 42 outputStream.write(data,0,len); 43 } 44 jsonString=new String(outputStream.toByteArray()); 45 } catch (IOException e) { 46 // TODO Auto-generated catch block 47 e.printStackTrace(); 48 } 49 return jsonString; 50 } 51 }
从IIS上获取到Json数据之后,需要新建一个类来解析服务端获取到的Json数据:
1 package cn.bgxt.jsonUtils; 2 3 import java.util.ArrayList; 4 import java.util.HashMap; 5 import java.util.List; 6 import java.util.Map; 7 8 import org.json.JSONArray; 9 import org.json.JSONObject; 10 11 import cn.bgxt.domain.Person; 12 13 public class JsonTools { 14 15 public JsonTools() { 16 // TODO Auto-generated constructor stub 17 } 18 19 public static Person getPerson(String jsonString) 20 { 21 Person person=new Person(); 22 try { 23 //一个Json对象,使用JSONObject 24 JSONObject jsonObject=new JSONObject(jsonString); 25 //对JSONObject对象中直接以key的形式取其Value 26 person.setId(jsonObject.getInt("id")); 27 person.setName(jsonObject.getString("name")); 28 person.setAge(jsonObject.getInt("age")); 29 } catch (Exception e) { 30 // TODO: handle exception 31 } 32 return person; 33 } 34 35 public static List<Person> getPersonList(String jsonString) 36 { 37 List<Person> list=new ArrayList<Person>(); 38 try { 39 //最外层是一个数组[],所以使用JSONArray 40 JSONArray jsonarr=new JSONArray(jsonString); 41 Person person=null; 42 for(int i=0;i<jsonarr.length();i++) 43 { 44 //遍历数组获得数组中Json对象。 45 person=new Person(); 46 JSONObject jsonObject= jsonarr.getJSONObject(i); 47 //获取到Json对象,就可以直接通过Key获取Value 48 person.setId(jsonObject.getInt("id")); 49 person.setName(jsonObject.getString("name")); 50 person.setAge(jsonObject.getInt("age")); 51 list.add(person); 52 } 53 } catch (Exception e) { 54 // TODO: handle exception 55 } 56 return list; 57 58 } 59 60 public static List<String> getStringList(String jsonString) 61 { 62 List<String> list=new ArrayList<String>(); 63 try { 64 JSONArray jsonArray=new JSONArray(jsonString); 65 for(int i =0;i<jsonArray.length();i++) 66 { 67 String str=jsonArray.getString(i); 68 list.add(str); 69 } 70 } catch (Exception e) { 71 // TODO: handle exception 72 } 73 return list; 74 } 75 76 public static List<Map<String, Object>> getMapList(String jsonString) 77 { 78 List<Map<String, Object>> maps=new ArrayList<Map<String,Object>>(); 79 try { 80 //最外层是一个Json数组 81 JSONArray jsonArray=new JSONArray(jsonString); 82 for(int i =0;i<jsonArray.length();i++) 83 { 84 //Json数组中又包含了一个Json数组 85 Map<String,Object> map=new HashMap<String, Object>(); 86 JSONArray mapArray=jsonArray.getJSONArray(i); 87 for(int j=0;j<mapArray.length();j++) 88 { 89 //第二层Json数组中才能取到Json对象,有对象就可以取值。 90 JSONObject jsonObject=mapArray.getJSONObject(j); 91 String key=jsonObject.getString("Key"); 92 Object value=jsonObject.get("Value"); 93 map.put(key, value); 94 } 95 maps.add(map); 96 } 97 } catch (Exception e) { 98 // TODO: handle exception 99 } 100 return maps; 101 102 } 103 104 105 }
再就是在Activity中添加4个按钮,分别响应这四次解析,布局相对简单,仅四个按钮,此处不给出布局代码,有兴趣的可以下载源码查看。因为是Android4.0+的平台,所以不能在主线程中访问网络,需要另起线程,还有别忘记增加访问网络的权限。
Activity代码:
1 package cn.bgxt.jsonparser; 2 3 import java.util.List; 4 import java.util.Map; 5 6 import cn.bgxt.domain.Person; 7 import cn.bgxt.http.HttpUtils; 8 import cn.bgxt.jsonUtils.JsonTools; 9 import android.os.Bundle; 10 import android.app.Activity; 11 import android.util.Log; 12 import android.view.Menu; 13 import android.view.View; 14 import android.view.View.OnClickListener; 15 import android.widget.Button; 16 17 public class MainActivity extends Activity implements OnClickListener { 18 19 private String path_url = "http://192.168.1.106:1231/json/returnJson.ashx?JsonData="; 20 private Button person, personList, stringList, dicList; 21 private String path = ""; 22 23 @Override 24 protected void onCreate(Bundle savedInstanceState) { 25 super.onCreate(savedInstanceState); 26 setContentView(R.layout.activity_main); 27 28 person = (Button) findViewById(R.id.person); 29 personList = (Button) findViewById(R.id.personList); 30 stringList = (Button) findViewById(R.id.stringList); 31 dicList = (Button) findViewById(R.id.dicList); 32 person.setOnClickListener(this); 33 personList.setOnClickListener(this); 34 stringList.setOnClickListener(this); 35 dicList.setOnClickListener(this); 36 } 37 38 @Override 39 public boolean onCreateOptionsMenu(Menu menu) { 40 getMenuInflater().inflate(R.menu.main, menu); 41 return true; 42 } 43 44 @Override 45 public void onClick(View v) { 46 47 switch (v.getId()) { 48 case R.id.person: 49 Thread thread = new Thread(new Runnable() { 50 51 @Override 52 public void run() { 53 // TODO Auto-generated method stub 54 path = path_url + "Person"; 55 String jsonString = HttpUtils.getJsonContent(path); 56 Person person = JsonTools.getPerson(jsonString); 57 Log.i("main", person.toString()); 58 } 59 }); 60 thread.start(); 61 break; 62 case R.id.personList: 63 Thread thread1 = new Thread(new Runnable() { 64 @Override 65 public void run() { 66 // TODO Auto-generated method stub 67 path = path_url + "PersonList"; 68 String jsonString = HttpUtils.getJsonContent(path); 69 List<Person> persons = JsonTools.getPersonList(jsonString); 70 for(Person p:persons) 71 { 72 Log.i("main", p.toString()); 73 } 74 } 75 }); 76 thread1.start(); 77 break; 78 case R.id.stringList: 79 Thread thread2 = new Thread(new Runnable() { 80 @Override 81 public void run() { 82 // TODO Auto-generated method stub 83 path = path_url + "StringList"; 84 String jsonString = HttpUtils.getJsonContent(path); 85 List<String> strings = JsonTools.getStringList(jsonString); 86 for(String s:strings) 87 { 88 Log.i("main", s); 89 } 90 } 91 }); 92 thread2.start(); 93 break; 94 case R.id.dicList: 95 Thread thread3 = new Thread(new Runnable() { 96 @Override 97 public void run() { 98 // TODO Auto-generated method stub 99 path = path_url + "DicList"; 100 String jsonString = HttpUtils.getJsonContent(path); 101 List<Map<String, Object>> maps = JsonTools.getMapList(jsonString); 102 for(Map<String, Object> m:maps) 103 { 104 Log.i("main", m.toString()); 105 } 106 } 107 }); 108 thread3.start(); 109 break; 110 } 111 112 } 113 114 }
依次按顺序点击按钮,可以再LogCat中查看数据:
总结
本来Java中有一套自己的序列化办法,序列化出来的Json数据并不是如此的格式,可这里使用的.Net序列化的办法,但是参照本文的思想,只要知道Json的格式,无论Json数据变什么样子,都是可以解析出来的。真实的Android开发服务端的时候,还是尽量使用Java来开发,减少兼容性的问题。
请支持原创,尊重原创,转载请注明出处。谢谢。