上篇随笔详细介绍了三种解析服务器端传过来的xml数据格式,而对于服务器端来讲,返回给客户端的数据格式通常分为html、xml和json这三种格式,那么本篇随笔将讲解一下json这个知识点,包括如何经过json-lib和gson这两个json解析库来对解析咱们的json数据,以及如何在咱们的Android客户端解析来自服务器端的json数据,并更新到UI当中。javascript
1、什么是jsonhtml
json(Javascript Object Notation)是一种轻量级的数据交换格式,相比于xml这种数据交换格式来讲,由于解析xml比较的复杂,并且须要编写大段的代码,因此客户端和服务器的数据交换格式每每经过json来进行交换。尤为是对于web开发来讲,json数据格式在客户端直接能够经过javascript来进行解析。java
json一共有两种数据结构,一种是以 (key/value)对形式存在的无序的jsonObject对象,一个对象以“{”(左花括号)开始,“}”(右花括号)结束。每一个“名称”后跟一个“:”(冒号);“‘名称/值’ 对”之间使用“,”(逗号)分隔。android
例如:{"name": "xiaoluo"}, 这就是一个最简单的json对象,对于这种数据格式,key值必需要是string类型,而对于value,则能够是string、number、object、array等数据类型:web
另外一种数据格式就是有序的value的集合,这种形式被称为是jsonArray,数组是值(value)的有序集合。一个数组以“[”(左中括号)开始,“]”(右中括号)结束。值之间使用“,”(逗号)分隔。json
更多的有关json数据格式能够参加json的官网,http://www.json.org/json-zh.html数组
2、解析json数据格式服务器
这里将使用两种json的解析库来对咱们的json数据格式进行解析以及生成咱们的json数据格式。网络
1.json-lib(http://json-lib.sourceforge.net/)数据结构
使用json-lib来进行解析,咱们须要引入第三方的包,由于json-lib分为了两个版本,一个版本是针对于jdk1.3的,一个版本是针对于jdk1.5的,这里咱们下载jdk1.5的这个json-lib包,其中还须要引入其余的几个jar包:
下载好这几个jar包后,加入到classpath中便可。咱们来看看json-lib给咱们提供的API。
咱们最经常使用的两个类就是 JSONObject和JSONArray这两个类,分别表明了json对象和json数组,这两个类都实现了 JSON 这个接口,下面咱们经过几个小例子来看看如何将咱们常见的几种数据格式转换成咱们的json对象(咱们通常称之为JSON数据的序列化)以及再将json对象在转换成咱们的数据格式(称之为反序列化)。
①简单的javabean的序列化和反序列化
public class Person { private int id; private String name; private String address; public Person() { } 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; } public Person(int id, String name, String address) { super(); this.id = id; this.name = name; this.address = address; } @Override public String toString() { return "Person [id=" + id + ", name=" + name + ", address=" + address + "]"; } }
首先咱们定义一个简单的javabean对象,而后将一个Person对象转换成json对象,而后再将这个json对象反序列化成咱们的Person对象。
咱们先定义一个JsonTools类,这个类有两个静态方法,咱们能够经过这两个方法来获得一个JSON类型的字符串对象,以及一个JSON对象
public class JsonTools { /** * 获得一个json类型的字符串对象 * @param key * @param value * @return */ public static String getJsonString(String key, Object value) { JSONObject jsonObject = new JSONObject(); //put和element都是往JSONObject对象中放入 key/value 对 // jsonObject.put(key, value); jsonObject.element(key, value); return jsonObject.toString(); } /** * 获得一个json对象 * @param key * @param value * @return */ public static JSONObject getJsonObject(String key, Object value) { JSONObject jsonObject = new JSONObject(); jsonObject.put(key, value); return jsonObject; } }
咱们能够直接经过 JSONObject jsonObject = new JSONObject(); 这个方法就能够获得一个json对象,而后经过element()或者是put()方法来给咱们的json对象添加key/value对。咱们先来看看第一个例子,实现一个简单的Person对象和json对象的转换
Person person = new Person(1, "xiaoluo", "广州"); // 将Person对象转换成一个json类型的字符串对象 String personString = JsonTools.getJsonString("person", person); System.out.println(personString.toString());
咱们看看控制台的输出:
{"person":{"address":"广州","id":1,"name":"xiaoluo"}}
整个外面的大括号是一个json对象,里面有一对key/value,其中里面的{"address":"广州","id":1,"name":"xiaoluo"}就是咱们转换成的json字符串对象
再来看看如何将json对象转换成咱们的bean对象
JSONObject jsonObject = JsonTools.getJsonObject("person", person); // 经过JSONObject的toBean方法能够将json对象转换成一个javabean JSONObject personObject = jsonObject.getJSONObject("person"); Person person2 = (Person) JSONObject.toBean(personObject, Person.class); System.out.println(person2);
Person [id=1, name=xiaoluo, address=广州]
②转换List<Person>类型的对象
@Test public void testPersonsJson() { List<Person> persons = new ArrayList<Person>(); Person person = new Person(1, "xiaoluo", "广州"); Person person2 = new Person(2, "android", "上海"); persons.add(person); persons.add(person2); String personsString = JsonTools.getJsonString("persons", persons); System.out.println(personsString); JSONObject jsonObject = JsonTools.getJsonObject("persons", persons); // List<Person>至关于一个JSONArray对象 JSONArray personsArray = (JSONArray)jsonObject.getJSONArray("persons"); List<Person> persons2 = (List<Person>) personsArray.toCollection(personsArray, Person.class); System.out.println(persons2); }
{"persons":[{"address":"广州","id":1,"name":"xiaoluo"},{"address":"上海","id":2,"name":"android"}]} [Person [id=1, name=xiaoluo, address=广州], Person [id=2, name=android, address=上海]]
③List<Map<String, String>>类型的json对象转换
@Test public void testMapJson() { List<Map<String, String>> list = new ArrayList<Map<String, String>>(); Map<String, String> map1 = new HashMap<String, String>(); map1.put("id", "001"); map1.put("name", "xiaoluo"); map1.put("age", "20"); Map<String, String> map2 = new HashMap<String, String>(); map2.put("id", "002"); map2.put("name", "android"); map2.put("age", "33"); list.add(map1); list.add(map2); String listString = JsonTools.getJsonString("list", list); System.out.println(listString); JSONObject jsonObject = JsonTools.getJsonObject("list", list); JSONArray listArray = jsonObject.getJSONArray("list"); List<Map<String, String>> list2 = (List<Map<String, String>>) listArray.toCollection(listArray, Map.class); System.out.println(list2); }
{"list":[{"id":"001","age":"20","name":"xiaoluo"},{"id":"002","age":"33","name":"android"}]} [{id=001, name=xiaoluo, age=20}, {id=002, name=android, age=33}]
经过上面的例子,咱们能够了解了如何经过json-lib这个解析库来实现javabean、List、Map等数据和json数据的互相转换
2.gson(http://code.google.com/p/google-gson/)
下面咱们来看看Google提供的gson这个json解析库,一样咱们须要去下载gson这个jar包,导入到咱们的项目中
使用gson,咱们能够很是轻松的实现数据对象和json对象的相互转化,其中咱们最经常使用的就是两个方法,一个是fromJSON(),将json对象转换成咱们须要的数据对象,另外一个是toJSON(),这个就是将咱们的数据对象转换成json对象。下面咱们也经过一个综合的例子来看看gson的使用方法:
public class JsonService { public Person getPerson() { Person person = new Person(1, "xiaoluo", "广州"); return person; } public List<Person> getPersons() { List<Person> persons = new ArrayList<Person>(); Person person = new Person(1, "xiaoluo", "广州"); Person person2 = new Person(2, "android", "上海"); persons.add(person); persons.add(person2); return persons; } public List<String> getString() { List<String> list = new ArrayList<String>(); list.add("广州"); list.add("上海"); list.add("北京"); return list; } public List<Map<String, String>> getMapList() { List<Map<String, String>> list = new ArrayList<Map<String, String>>(); Map<String, String> map1 = new HashMap<String, String>(); map1.put("id", "001"); map1.put("name", "xiaoluo"); map1.put("age", "20"); Map<String, String> map2 = new HashMap<String, String>(); map2.put("id", "002"); map2.put("name", "android"); map2.put("age", "33"); list.add(map1); list.add(map2); return list; } }
public static void main(String[] args) { Gson gson = new Gson(); JsonService jsonService = new JsonService(); Person person = jsonService.getPerson(); System.out.println("person: " + gson.toJson(person)); // 对于Object类型,使用 fromJson(String, Class)方法来将Json对象转换成Java对象 Person person2 = gson.fromJson(gson.toJson(person), Person.class); System.out.println(person2); System.out.println("------------------------------------------------"); List<Person> persons = jsonService.getPersons(); System.out.println("persons: " + gson.toJson(persons)); /* * 对于泛型对象,使用fromJson(String, Type)方法来将Json对象转换成对应的泛型对象 * new TypeToken<>(){}.getType()方法 */ List<Person> persons2 = gson.fromJson(gson.toJson(persons), new TypeToken<List<Person>>(){}.getType()); System.out.println(persons2); System.out.println("------------------------------------------------"); List<String> list = jsonService.getString(); System.out.println("String---->" + gson.toJson(list)); List<String> list2 = gson.fromJson(gson.toJson(list), new TypeToken<List<String>>(){}.getType()); System.out.println("list2---->" + list2); System.out.println("------------------------------------------------"); List<Map<String, String>> listMap = jsonService.getMapList(); System.out.println("Map---->" + gson.toJson(listMap)); List<Map<String, String>> listMap2 = gson.fromJson(gson.toJson(listMap), new TypeToken<List<Map<String, String>>>(){}.getType()); System.out.println("listMap2---->" + listMap2); System.out.println("------------------------------------------------"); }
看看控制台的输出:
person: {"id":1,"name":"xiaoluo","address":"广州"} Person [id=1, name=xiaoluo, address=广州] ------------------------------------------------ persons: [{"id":1,"name":"xiaoluo","address":"广州"},{"id":2,"name":"android","address":"上海"}] [Person [id=1, name=xiaoluo, address=广州], Person [id=2, name=android, address=上海]] ------------------------------------------------ String---->["广州","上海","北京"] list2---->[广州, 上海, 北京] ------------------------------------------------ Map---->[{"id":"001","age":"20","name":"xiaoluo"},{"id":"002","age":"33","name":"android"}] listMap2---->[{id=001, age=20, name=xiaoluo}, {id=002, age=33, name=android}] ------------------------------------------------
3、在Android客户端解析服务器端的json数据
下面咱们来完成一个综合的例子,Android客户端经过一个AsyncTask异步任务请求服务器端的某些数据,而后在解析完这些数据后,将获得的数据内容更新到咱们的Spinner这个UI控件当中。
咱们首先来看下服务器端的代码:
@WebServlet("/CityServlet") public class CityServlet extends HttpServlet { private static final long serialVersionUID = 1L; public CityServlet() { super(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } protected 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 writer = response.getWriter(); String type = request.getParameter("type"); if("json".equals(type)) { List<String> cities = new ArrayList<String>(); cities.add("广州"); cities.add("上海"); cities.add("北京"); cities.add("湖南"); Map<String, List<String>> map = new HashMap<String, List<String>>(); map.put("cities", cities); String citiesString = JSON.toJSONString(map); writer.println(citiesString); } writer.flush(); writer.close(); } }
若是客户端请求的参数是type=json,则响应给客户端一个json数据格式
接着来看看客户端的代码,首先看看客户端的布局文件,其实就是一个按钮和一个Spinner控件,当点击按钮后,经过http协议请求服务器端的数据,而后在接收到后再更新咱们的Spinner控件的数据
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" > <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:layout_marginLeft="64dp" android:layout_marginTop="64dp" android:textSize="20sp" android:text="城市" /> <Spinner android:id="@+id/spinner" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignTop="@id/textView1" android:layout_toRightOf="@id/textView1"/> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/textView1" android:layout_below="@+id/spinner" android:layout_marginLeft="22dp" android:layout_marginTop="130dp" android:text="加载数据" /> </RelativeLayout>
在Android客户端写一个解析json数据格式的类:
public class JsonUtils { /** * @param citiesString 从服务器端获得的JSON字符串数据 * @return 解析JSON字符串数据,放入List当中 */ public static List<String> parseCities(String citiesString) { List<String> cities = new ArrayList<String>(); try { JSONObject jsonObject = new JSONObject(citiesString); JSONArray jsonArray = jsonObject.getJSONArray("cities"); for(int i = 0; i < jsonArray.length(); i++) { cities.add(jsonArray.getString(i)); } } catch (Exception e) { e.printStackTrace(); } return cities; } }
固然咱们的HttpUtils类也不可少:
public class HttpUtils { /** * @param path 请求的服务器URL地址 * @param encode 编码格式 * @return 将服务器端返回的数据转换成String */ public static String sendPostMessage(String path, String encode) { String result = ""; HttpClient httpClient = new DefaultHttpClient(); try { HttpPost httpPost = new HttpPost(path); HttpResponse httpResponse = httpClient.execute(httpPost); if(httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { HttpEntity httpEntity = httpResponse.getEntity(); if(httpEntity != null) { result = EntityUtils.toString(httpEntity, encode); } } } catch (Exception e) { e.printStackTrace(); } finally { httpClient.getConnectionManager().shutdown(); } return result; } }
最后来看看咱们的MainActivity类:
public class MainActivity extends Activity { private Spinner spinner; private Button button; private ArrayAdapter<String> adapter; private ProgressDialog dialog; private final String CITY_PATH_JSON = "http://172.25.152.34:8080/httptest/CityServlet?type=json"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); spinner = (Spinner)findViewById(R.id.spinner); button = (Button)findViewById(R.id.button); dialog = new ProgressDialog(MainActivity.this); button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { dialog.setTitle("提示信息"); dialog.setMessage("loading......"); dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); dialog.setCancelable(false); new MyAsyncTask().execute(CITY_PATH_JSON); } }); } public class MyAsyncTask extends AsyncTask<String, Void, List<String>> { @Override protected void onPreExecute() { dialog.show(); } @Override protected List<String> doInBackground(String... params) { List<String> cities = new ArrayList<String>(); String citiesString = HttpUtils.sendPostMessage(params[0], "utf-8"); // 解析服务器端的json数据 cities = JsonUtils.parseCities(citiesString);return cities; } @Override protected void onPostExecute(List<String> result) { adapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_spinner_item, result); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinner.setAdapter(adapter); dialog.dismiss(); } } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); return true; } }
固然别往了开启咱们的网络受权
<uses-permission android:name="android.permission.INTERNET"/>
最后咱们来看看效果图:
这样咱们就完成了客户端与服务器端经过json来进行数据的交换
总结:本篇随笔主要讲解了JSON这种轻量级的数据交换格式的概念,以及讲解了两种解析json数据的解析类(json-lib以及gson),最后经过一个小例子实现了在Android客户端和服务器端使用json这种数据格式来进行数据的交换。