JSON(JavaScript Object Notation) 和 XML,并称为客户端和服务端交互解决方案的倚天剑和屠龙刀,这篇文章主要介绍了 Android 系列 ---JSON 数据解析的实例,有兴趣的可以了解一下。
Android 是一种基于 Linux 的自由及开放源代码的操作系统,主要使用于移动设备,如智能手机和平板电脑,由 Google 公司和开放手机联盟领导及开发。尚未有统一中文名称,中国大陆地区较多人使用 "安卓" 或 "安致"。
上篇随笔详细介绍了三种解析服务器端传过来的 xml 数据格式,而对于服务器端来说,返回给客户端的数据格式一般分为 html、xml 和 json 这三种格式,那么本篇随笔将讲解一下 json 这个知识点,包括如何通过 json-lib 和 gson 这两个 json 解析库来对解析我们的 json 数据,以及如何在我们的 Android 客户端解析来自服务器端的 json 数据,并更新到 UI 当中。
一、什么是 json
json(Javascript Object Notation) 是一种轻量级的数据交换格式,相比于 xml 这种数据交换格式来说,因为解析 xml 比较的复杂,而且需要编写大段的代码,所以客户端和服务器的数据交换格式往往通过 json 来进行交换。尤其是对于 web 开发来说,json 数据格式在客户端直接可以通过 javascript 来进行解析。
json 一共有两种数据结构,一种是以 (key/value) 对形式存在的无序的 jsonObject 对象,一个对象以 "{"(左花括号)开始,"}"(右花括号)结束。每个 "名称" 后跟一个 ":"(冒号);"'名称 / 值' 对 "之间使用","(逗号)分隔。
例如:{"name": "xiaoluo"}, 这就是一个最简单的 json 对象,对于这种数据格式,key 值必须要是 string 类型,而对于 value,则可以是 string、number、object、array 等数据类型:
另一种数据格式就是有序的 value 的集合,这种形式被称为是 jsonArray,数组是值(value)的有序集合。一个数组以 "["(左中括号)开始,"]"(右中括号)结束。值之间使用 ","(逗号)分隔。
更多的有关 json 数据格式可以参加 json 的官网,{aa2aa}
二、解析 json 数据格式
这里将使用两种 json 的解析库来对我们的 json 数据格式进行解析以及生成我们的 json 数据格式。
1.json-lib({aa1aa})
使用 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
- @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
- @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({aa0aa})
下面我们来看看 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}]
------------------------------------------------
三、在 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 这种数据格式来进行数据的交换。
来源: http://www.phperz.com/article/17/0313/307145.html