在前面的两讲中,我们讲解了JSON数据格式的一些基本知识,以及做一些小Demo,这一讲我们在前面的基础上来做一个综合的可扩展的Demo,主要是针对Android客户端解析服务端传递过来的JSON数据。整个Demo所作的操作如下图所示


1. 服务端

   服务端我们需要用到的解析JSON的库是用org.json --> Java --> JSON-lib项目中的库json-lib-2.4-jdk15.jar,这个库还需要附带几个依赖包:commons-beanutils.jar, commons-httpclient.jar, commons- lang.jar, ezmorph.jar,morph-1.0.1.jar。具体的包我会放在源码的lib目录下,读者可以自己去下载。

   查看这个项目的api文档:http://json-lib.sourceforge.net/apidocs/jdk15/index.html,我们主要使用的是JSON JSONArray JSONObject JSONSerializer 这几个类,JSONObject这个类可以发现它与org.json这个项目的用法很类似。

   1) 先做一个服务端的小实验,就是在服务端实现对Java对象转换成JSON数据格式并且在控制台输出。

Person.java 普通的Person类

package com.json.domain;public class Person {    private int id;    private String name;    private String address;    public Person(int id, String name, String address) {        super();        this.id = id;        this.name = name;        this.address = address;    }    public Person() {        // TODO Auto-generated constructor stub    }    public int getId() {        return id;    }    public void setId(int id) {        this.id = id;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public String getAddress() {        return address;    }    public void setAddress(String address) {        this.address = address;    }}

JsonService.java 服务于Person,给Person对象赋予各种属性

package com.json.service;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import com.json.domain.Person;public class JsonService {       public JsonService() {        // TODO Auto-generated constructor stub    }    public Person getPerson(){        Person person = new Person(23, "AHuier", "XIAMEN");        return person;    }        public List getListPerson(){        List list = new ArrayList();        Person person1 = new Person(1001, "AHuier1", "Beijing");        Person person2 = new Person(1002, "AHuier2", "shenzheng");        list.add(person1);        list.add(person2);        return list;    }        public List getListString(){        List list = new ArrayList();        list.add("Hello");        list.add("World");        list.add("AHuier");        return list;    }        public List> getListMaps(){        List> listMap = new ArrayList>();        Map map1 = new HashMap();        map1.put("color", "red");        map1.put("id", 01);        map1.put("name", "Polu");        listMap.add(map1);        Map map2 = new HashMap();        map2.put("id", 07);        map2.put("color", "green");        map2.put("name", "Zark");        listMap.add(map2);        return listMap;     }   }
JsonTools.java 工具类
package com.json.tools;import net.sf.json.JSONObject;/** * @author xukunhui * 工具类,这里专门处理Java对象转Json字符串的功能 */public class JsonTools {    public JsonTools() {        // TODO Auto-generated constructor stub    }    /**     * @param key : JSON 名值对中的的名字     * @param value :JSON 名值对中的值,值可以有多种类型     * @return     */    // 接受对象转换为JSON数据格式并且作为字符串输出.    public static String createJsonString(String key, Object value){        JSONObject jsonObject = new JSONObject();        jsonObject.put(key, value);        return jsonObject.toString(); //就可以转换成Json数据格式    }    }
JsonTest.java 测试类
package com.json.test;import com.json.domain.Person;import com.json.service.JsonService;import com.json.tools.JsonTools;/** * @author xukunhui * 测试类,利用JSON讲Java对象转换成JSON数据格式,并且在控制台中输出 */public class JsonTest {    public JsonTest() {        // TODO Auto-generated constructor stub    }    /**     * @param args     */    public static void main(String[] args) {        // TODO Auto-generated method stub        String msg = "";        JsonService service = new JsonService();        // 带有三个属性的person对象        Person person = service.getPerson();        msg = JsonTools.createJsonString("person", person);        System.out.println(msg);                System.out.println("------------------------------");        // List中存放两个person对象,这两个对象有各自的三个属性        msg = JsonTools.createJsonString("persons", service.getListPerson());        System.out.println(msg);                System.out.println("------------------------------");        // List中存放三个字符串        msg = JsonTools.createJsonString("listString", service.getListString());        System.out.println(msg);                System.out.println("------------------------------");        // List中存放两个Map,两个Map中分别存放三个不同的属性        msg = JsonTools.createJsonString("listMap", service.getListMaps());        System.out.println(msg);            }}

编译执行结果:

{"person":{"address":"XIAMEN","id":23,"name":"AHuier"}}
------------------------------
{"persons":[{"address":"Beijing","id":1001,"name":"AHuier1"},{"address":"shenzheng","id":1002,"name":"AHuier2"}]}
------------------------------
{"listString":["Hello","World","AHuier"]}
------------------------------
{"listMap":[{"id":1,"color":"red","name":"Polu"},{"id":7,"color":"green","name":"Zark"}]}

【说明】:从这里可以发现在服务端利用JSON很方便的将Java对象转换成JSON数据格式。

【注意】:我们这边需要给加一个person的标示符,作为最外面的一个对象的名,我们在客户端解析数据的时候,其实不加person的标示符也是可以的,但是这样写的目的是把原有的对象转换成JSON数据格式之后,我们在外层再给予封装一层对象,便于后续利用外层的这个对象进行解析。如下图所示:


2) 现在我们将服务端的项目部署到Tomcat服务器(如何部署可以参考前面几篇博文),然后通过在浏览器的地址栏中传递不同的action值来获取相应的JSON数据格式,这样的话浏览器也会显示出请求服务解析好的JSON数据格式。实现好这一步骤之后,我们在服务端的工作也完成了。服务端的项目结构图如下所示:


JsonAction.java  Servlet类,处理根浏览器客户端通过不同的参数请求返回JSON数据。

package com.json.action;import java.io.IOException;import java.io.PrintWriter;import java.nio.charset.Charset;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import com.json.service.JsonService;import com.json.tools.JsonTools;/** * @author xukunhui * Servlet类,处理根浏览器客户端通过不同的参数请求返回JSON数据。 */public class JsonAction extends HttpServlet {    private JsonService service;        /**     * Constructor of the object.     */    public JsonAction() {        super();    }    /**     * Destruction of the servlet. 
*/ public void destroy() { super.destroy(); // Just puts "destroy" string in log // Put your code here } /** * The doGet method of the servlet.
* * This method is called when a form has its tag value method equals to get. * * @param request the request send by the client to the server * @param response the response send by the server to the client * @throws ServletException if an error occurred * @throws IOException if an error occurred */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } /** * The doPost method of the servlet.
* * This method is called when a form has its tag value method equals to post. * * @param request the request send by the client to the server * @param response the response send by the server to the client * @throws ServletException if an error occurred * @throws IOException if an error occurred */ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html; Charset=utf-8"); request.setCharacterEncoding("utf-8"); response.setCharacterEncoding("utf-8"); PrintWriter out = response.getWriter();         /*            * 如果是以下这种方式直接在浏览器地址栏中用  http://192.168.0.112:8080/JsonProject/servlet/JsonAction 请求即可         * String jsonString = JsonTools.createJsonString("person", service.getListPerson());         * out.print(jsonString); // 从服务端提取数据,并且输出的浏览器客户端。        */     // 根据不同的参数输出不同的JSON数据 String jsonString = ""; String action_flag = request.getParameter("action_flag"); if(action_flag.equals("person")) { jsonString = JsonTools.createJsonString("person", service.getPerson()); } else if(action_flag.equals("persons")){ jsonString = JsonTools.createJsonString("persons", service.getListPerson()); } else if(action_flag.equals("listString")) { jsonString = JsonTools.createJsonString("listString", service.getListString()); } else if(action_flag.equals("listMap")){ jsonString = JsonTools.createJsonString("listMap", service.getListMaps()); } out.print(jsonString); out.flush(); out.close(); } /** * Initialization of the servlet.
* * @throws ServletException if an error occurs */ public void init() throws ServletException { // Put your code here service = new JsonService(); }}
程序执行, 浏览器地址栏中输入与浏览器显示如下:

输入: http://192.168.0.112:8080/JsonProject/servlet/JsonAction?action_flag=person
输出: {"person":{"address":"XIAMEN","id":23,"name":"AHuier"}}

输入:http://192.168.0.112:8080/JsonProject/servlet/JsonAction?action_flag=persons
输出: {"persons":[{"address":"Beijing","id":1001,"name":"AHuier1"},{"address":"shenzheng","id":1002,"name":"AHuier2"}]}

输入:http://192.168.0.112:8080/JsonProject/servlet/JsonAction?action_flag=listString
输出: {"listString":["Hello","World","AHuier"]}

输入:http://192.168.0.112:8080/JsonProject/servlet/JsonAction?action_flag=listMap
输出: {"listMap":[{"id":1,"color":"red","name":"Polu"},{"id":7,"color":"green","name":"Zark"}]}

【备注】:自此,我们服务端模块的内容已经实现的差不多了,在服务端我们通常还结合JDBC进行操作。可以把JDBC的数据提取出来,提取出来的肯定是单条记录,或者是某一个集合。也就是服务端从JDBC数据库中提取到数据只要转换成JSON的数据格式后提供客户端进行显示。如下图所示:


2. 客户端

   上面我们已经写好了服务端的代码,现在我们开始进行Android客户端的操作。JSON的解析有一个规则就是服务端把对象转换成一个JSON的数据格式,而客户端需要把JSON格式换成对象,客户端主要是通过Http协议向服务端发出请求获得服务端的JSON数据。

   客户端项目结构如下图所示:

  

1. 客户端需要通过网络去向服务端请求数据,所以需要在 manifest.xml 清单文件中定义好访问网络的属性

        
2. HttpUtils.java 负责从服务器请求获取到JSON数据格式的字符串
package com.android.jsonproject.http;import java.io.ByteArrayOutputStream;import java.io.InputStream;import java.net.HttpURLConnection;import java.net.URL;/** * @author xukunhui 从服务器请求获取到JSON数据格式的字符串 */public class HttpUtils {    public HttpUtils() {        // TODO Auto-generated constructor stub    }    public static String getJsonContent(String url_path) {        try {            URL url = new URL(url_path);            HttpURLConnection connection = (HttpURLConnection) url.openConnection();            connection.setConnectTimeout(3000); // 请求超时时间3s            connection.setRequestMethod("GET");            connection.setDoInput(true);            int code = connection.getResponseCode(); // 返回状态码            if (code == 200) {                // 或得到输入流,此时流里面已经包含了服务端返回回来的JSON数据了,此时需要将这个流转换成字符串                return changeInputStream(connection.getInputStream());            }        } catch (Exception e) {            // TODO: handle exception        }        return "";    }    private static String changeInputStream(InputStream inputStream) {        // TODO Auto-generated method stub        String jsonString = "";        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();        int length = 0;        byte[] data = new byte[1024];        try {            while (-1 != (length = inputStream.read(data))) {                outputStream.write(data, 0, length);            }            // inputStream流里面拿到数据写到ByteArrayOutputStream里面,            // 然后通过outputStream.toByteArray转换字节数组,再通过new String()构建一个新的字符串。            jsonString = new String(outputStream.toByteArray());        } catch (Exception e) {            // TODO: handle exception        }        return jsonString;    }}
3. JSONTools.java 完成对从服务端请求获得的JSON数据的解析成指定的对象.
package com.android.jsonproject.json;import java.util.ArrayList;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.Map;import org.json.JSONArray;import org.json.JSONObject;import com.android.jsonproject.domain.Person;/** * @author xukunhui * 完成对从服务端请求获得的JSON数据的解析成指定的对象. */public class JSONTools {    public JSONTools() {        // TODO Auto-generated constructor stub    }        // 此时从服务端取下来的数据是:{"person":{"address":"XIAMEN","id":23,"name":"AHuier"}}    public static Person getPerson(String key, String jsonString){        Person person = new Person();        try {            // 在Android官方文档中,org.json 这是Android提供给我们的解析json数据格式的包,            // 我们比较常用的是JSONArray 和 JSONObject这个两个类            JSONObject jsonObject = new JSONObject(jsonString);            JSONObject personObject = jsonObject.getJSONObject(key);            person.setId(personObject.getInt("id"));            person.setAddress(personObject.getString("address"));            person.setName(personObject.getString("name"));        } catch (Exception e) {            // TODO: handle exception        }        return person;    }        //{"persons":[{"address":"Beijing","id":1001,"name":"AHuier1"},{"address":"shenzheng","id":1002,"name":"AHuier2"}]}    public static List getPersons(String key, String jsonString){        List list = new ArrayList();        try {            JSONObject jsonObject = new JSONObject(jsonString);            //返回json的数组            JSONArray jsonArray = jsonObject.getJSONArray(key);            for(int i = 0; i < jsonArray.length(); i++){                JSONObject jsonObject2 = jsonArray.getJSONObject(i);                Person person = new Person();                person.setId(jsonObject2.getInt("id"));                person.setName(jsonObject2.getString("name"));                person.setAddress(jsonObject2.getString("address"));                list.add(person);            }        } catch (Exception e) {            // TODO: handle exception        }        return list;    }        //{"listString":["Hello","World","AHuier"]}    public static List getListString(String key, String jsonString){        List listString = new ArrayList();        try {            JSONObject jsonObject = new JSONObject(jsonString);            //返回JSON的数组            JSONArray jsonArray = jsonObject.getJSONArray(key);            for(int i = 0; i < jsonArray.length(); i++){                String msg = jsonArray.getString(i);                listString.add(msg);            }        } catch (Exception e) {            // TODO: handle exception        }        return listString;    }        // 此时从服务端取下来的数据是:{"listMap":[{"id":1,"color":"red","name":"Polu"},{"id":7,"color":"green","name":"Zark"}]}    public static List> getListMaps(String key, String jsonString){        List> listMap = new ArrayList>();        try {            JSONObject jsonObject = new JSONObject(jsonString);            JSONArray jsonArray = jsonObject.getJSONArray(key);            for(int i = 0; i < jsonArray.length(); i++){                JSONObject jsonObject2 = jsonArray.getJSONObject(i);                Map map = new HashMap();                // 通过org.json中的迭代器来取Map中的值。                Iterator iterator = jsonObject2.keys();                while(iterator.hasNext()) {                    String jsonKey = iterator.next();                    Object jsonValue = jsonObject2.get(jsonKey);                    //JSON的值是可以为空的,所以我们也需要对JSON的空值可能性进行判断。                    if(jsonValue == null){                        jsonValue = "";                    }                    map.put(jsonKey, jsonValue);                }                listMap.add(map);            }        } catch (Exception e) {            // TODO: handle exception        }        return listMap;    }    }
4. Person.java 配合客户端将JSON数据转换成Java对象,服务端有Person对象,所以客户端需要相应的Person对象
package com.android.jsonproject.domain;public class Person {    private int id;    private String name;    private String address;    public Person(int id, String name, String address) {        super();        this.id = id;        this.name = name;        this.address = address;    }    public Person() {        // TODO Auto-generated constructor stub    }    @Override    public String toString() {        return "Person [id=" + id + ", name=" + name + ", address=" + address + "]";    }    public int getId() {        return id;    }    public void setId(int id) {        this.id = id;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public String getAddress() {        return address;    }    public void setAddress(String address) {        this.address = address;    }}
5. Android 客户端主界面代码,这里主要是定义四个按钮分别处理解析不同类型的JSON数据格式,布局文件这里不再贴出.
    @Override    public void onClick(View v) {        // TODO Auto-generated method stub        switch (v.getId()) {            case R.id.person:                  String path = "http://192.168.0.112:8080/JsonProject/servlet/JsonAction?action_flag=person";                String jsonString = HttpUtils.getJsonContent(path);                Log.i(TAG, "The jsonString:" + jsonString);                Person person = JSONTools.getPerson("person", jsonString);                Log.i(TAG, "The person:" + person.toString());                break;            case R.id.persons:                String path2 = "http://192.168.0.112:8080/JsonProject/servlet/JsonAction?action_flag=persons";                String jsonString2 = HttpUtils.getJsonContent(path2);                Log.i(TAG, "The jsonString:" + jsonString2);                List list2 = JSONTools.getPersons("persons", jsonString2);                Log.i(TAG, "The persons:" + list2.toString());                break;            case R.id.liststring:                String path3 = "http://192.168.0.112:8080/JsonProject/servlet/JsonAction?action_flag=listString";                String jsonString3 = HttpUtils.getJsonContent(path3);                Log.i(TAG, "The jsonString:" + jsonString3);                List list3 = JSONTools.getListString("listString", jsonString3);                Log.i(TAG, "The listString:" + list3.toString());                break;            case R.id.listmap:                String path4 = "http://192.168.0.112:8080/JsonProject/servlet/JsonAction?action_flag=listMap";                String jsonString4 = HttpUtils.getJsonContent(path4);                Log.i(TAG, "The jsonString:" + jsonString4);                List> list4 = JSONTools.getListMaps("listMap", jsonString4);                Log.i(TAG, "The listMap:" + list4.toString());                break;        }    }
客户端编译执行结果:

1. 点击解析person数据按钮

2. 点击解析List嵌套person数据

3. 点击List嵌套String数据

4. 点击List嵌套Map数据

自此,Android客户端与服务之间的JSON数据交互的Demo就完成了,下面附上源代码,读者可以自行编译执行

服务端: MyEclipse + Tomcat + Servlet

客户端: Eclipse + Android(模拟器和真机都可以,但是必须保证通过IP地址可以访问)

源码下载:http://download.csdn.net/detail/xukunhui2/6546095

服务端(符JSON开源项目包路径:JsonProject\WebRoot\WEB-INF\lib):

客户端:http://download.csdn.net/detail/xukunhui2/6546117


接下去,我们会学习一下google-gson的数据格式的解析,敬请关注。


  

更多相关文章

  1. 快速开发框架Afinal的使用(数据库操作,HTTP请求,网络图片加载,控件绑
  2. JavaEye Android(安卓)客户端正式发布
  3. Android(安卓)RSA与Java RSA加密不同标准产生问题的解决方法
  4. Android之Android的数据存储--SD卡
  5. 新浪微博开放平台开发-android客户端(2)
  6. android差分更新之服务端
  7. Android开发小记--开发实用工具类--数据库操作类
  8. 深入Android【八】 —— Activity间数据传输
  9. mybatisplus的坑 insert标签insert into select无参数问题的解决

随机推荐

  1. android 布局之RelativeLayout(相对布局)
  2. ButterKnife 8.4添加使用
  3. Android(安卓)Dialog和AlertDialog的一些
  4. android SeekBar双滑块
  5. RxJava 链式调用流程源码记录分析(以map()
  6. Android之监听View的两个指头是放大和缩
  7. Spatialite for Android编译及测试
  8. IIS 添加mime 支持 apk,exe,.woff,IIS MIM
  9. Android(安卓)SDK——Android(安卓)Studi
  10. Android(安卓)开发笔记之界面开发