使用JSON 进行网络数据交换

来源:互联网 发布:期货行情分析软件 编辑:程序博客网 时间:2024/06/18 17:20

使用JSON 进行网络数据交换

标签 :

在开发客户端与服务端的应用当中,数据交换接口通常都是通过XML 格式来进行数据交换的。近年

来,随着AJAX 技术的兴起,JSON 作为一种轻量级的数据交换格式,以其易于阅读和编写的优点,也越

来越多的被使用到各个项目中。在Android SDK 中,也提供了JSON 的类库方便对JSON 格式的数据进行

处理。本文将快速讲解 JSON 格式,并通过代码示例演示如何分别在客户端和服务器端进行 JSON 格式

数据的处理。

什么是JSON

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于阅读和编写,同时也易于

机器解析和生成,非常适合于服务器与客户端的交互。JSON 采用与编程语言无关的文本格式,但是也使

用了类C 语言的习惯,这些特性使JSON 成为理想的数据交换格式。

和 XML 一样,JSON 也是基于纯文本的数据格式。由于 JSON 天生是为 JavaScript 准备的,因此,

JSON 的数据格式非常简单,您可以用 JSON 传输一个简单的 String,Number,Boolean,也可以传输

一个数组,或者一个复杂的 Object 对象。

String,Number 和 Boolean 用 JSON 表示非常简单。例如,用 JSON 表示一个简单的字符串

“ abc ”,其格式为:"abc"。

除了字符 ",\,/ 和一些控制符(\b,\f,\n,\r,\t)需要编码外,其他 Unicode 字符可以直接输出。

下图是一个 String 的完整表示结构:


图1.String 的完整表示结构

一个 Number 可以根据整型或浮点数表示如下:

图2.Number 的表示结构

这与绝大多数编程语言的表示方法一致,例如:

12345(整数)

-3.9e10(浮点数)

Boolean 类型表示为 true 或 false 。此外,JavaScript 中的 null 被表示为 null,注意,true、false

和 null 都没有双引号,否则将被视为一个 String 。

JSON 还可以表示一个数组对象,使用 [] 包含所有元素,每个元素用逗号分隔,元素可以是任意的

Value,例如,以下数组包含了一个 String,Number,Boolean 和一个 null:

view plaincopy to clipboardprint?

1. ["abc",12345,false,null]

Object 对象在 JSON 中是用 {} 包含一系列无序的 Key-Value 键值对表示的,实际上此处的

Object 相当于 Java 中的 Map<String, Object>,而不是 Java 的 Class 。注意 Key 只能用 String 表

示。例如,一个 Address 对象包含如下 Key-Value:

city:Beijing

street:Chaoyang Road

postcode:100025(整数)

用JSON 表示如下:

view plaincopy to clipboardprint?

1. {"city":"Beijing","street":" Chaoyang Road ","postcode":100025}

其中 Value 也可以是另一个 Object 或者数组,因此,复杂的 Object 可以嵌套表示,例如,一个

Person 对象包含 name 和 address 对象,可以表示如下:

view plaincopy to clipboardprint?

1. {"name":"Michael","address":

2. {"city":"Beijing","street":" Chaoyang Road ","postcode":100025}

3. }

一个实际例子

接下来,我会通过一个例子来详细说明Android 客户端程序如何访问服务端的接口程序读取用户列表

数据,并在模拟器上显示用户列表数据。

1、服务端接口程序

首先,我们创建一个名为User 的JavaBean 作为用户对象类,用来保存演示数据。

view plaincopy to clipboardprint?

1. public class User {

2. private int id;

3. private String name;

4. private String email;

5. private String gender;

6.

7. public int getId() {

8. return id;

9. }

10. public void setId(int id) {

11. this.id = id;

12. }

13. public String getName() {

14. return name;

15. }

16. public void setName(String name) {

17. this.name = name;

18. }

19. public String getEmail() {

20. return email;

21. }

22. public void setEmail(String email) {

23. this.email = email;

24. }

25. public String getGender() {

26. return gender;

27. }

28. public void setGender(String gender) {

29. this.gender = gender;

30. }

31.

32. }

接下来,我们创建一个名为JSONDemoServlet 的Servlet 类来作为服务端的接口程序。在这个程序里,

定义了一个List 对象用来保存用户列表。

view plaincopy to clipboardprint?

1. private List<User> list;

客户端程序访问服务器端接口时,接口通过prepareData 方法为用户列表初始化数据,添加用户数据

到List 对象中。

view plaincopy to clipboardprint?

1. private void prepareData(){

2. list = new ArrayList<User>();

3. User bean1 = new User();

4. bean1.setId(1001);

5. bean1.setName("Tony");

6. bean1.setEmail("tony@toeach.net");

7. bean1.setGender("male");

8. list.add(bean1);

9. ……

10. }

接着遍历用户列表,把列表中的每个Java 用户对象转换为JSONObject 对象,再加入到JSONArray

中去。

view plaincopy to clipboardprint?

1. JSONArray array = new JSONArray();

2. for(User bean:list){

3. //单个用户JSON 对象

4. JSONObject obj = new JSONObject();

5.

6. try{

7. obj.put("id", bean.getId());

8. obj.put("name", bean.getName());

9. obj.put("email", bean.getEmail());

10. obj.put("gender", bean.getGender());

11. } catch (Exception e) {}

12.

13. array.put(obj);

14. }

最后,通过 Servlet 输出 JSON 时,需要设置正确的 MIME 类型和字符编码。假定服务器使用 UTF-8

编码,则可以使用以下代码输出编码后的 JSON 文本:

view plaincopy to clipboardprint?

1. response.setContentType("text/plain");

2. response.setCharacterEncoding("UTF-8");

3. PrintWriter out = response.getWriter();

4. out.write(array.toString());

5. out.flush();

6. out.close();

7.

8. JSONDemoServlet.java 的完整代码如下:

9. import java.io.IOException;

10. import java.io.PrintWriter;

11. import java.util.ArrayList;

12. import java.util.List;

13.

14. import javax.servlet.ServletException;

15. import javax.servlet.http.HttpServlet;

16. import javax.servlet.http.HttpServletRequest;

17. import javax.servlet.http.HttpServletResponse;

18.

19. import org.json.JSONArray;

20. import org.json.JSONObject;

21.

22. public class JSONDemoServlet extends HttpServlet{

23. private static final long serialVersionUID = -7368225680407826

408L;

24. private List<User> list;

25.

26. /**

27. * 处理post 方式提交的数据

28. */

29. public void doPost(HttpServletRequest request, HttpServletRespon

se response)throws ServletException, IOException {

30. doGet(request,response);

31. }

32. /**

33. * 出来get 方式提交的数据

34. */

35. public void doGet(HttpServletRequest request, HttpServletResp

onse response) throws ServletException, IOException {

36. response.setContentType("text/plain");

37. response.setCharacterEncoding("UTF-8");

38. PrintWriter out = response.getWriter();

39.

40. //准备用户数据

41. prepareData();

42.

43. //JSON 数组

44. JSONArray array = new JSONArray();

45. for(User bean:list){

46. //单个用户JSON 对象

47. JSONObject obj = new JSONObject();

48.

49. try{

50. obj.put("id", bean.getId());

51. obj.put("name", bean.getName());

52. obj.put("email", bean.getEmail());

53. obj.put("gender", bean.getGender());

54. } catch (Exception e) {}

55.

56. array.put(obj);

57. }

58.

59. //输出

60. out.write(array.toString());

61. out.flush();

62. out.close();

63. }

64. private void prepareData(){

65. list = new ArrayList<User>();

66. User bean1 = new User();

67. bean1.setId(1001);

68. bean1.setName("Tony");

69. bean1.setEmail("tony@toeach.net");

70. bean1.setGender("male");

71. list.add(bean1);

72.

73. User bean2 = new User();

74. bean2.setId(1002);

75. bean2.setName("Jack");

76. bean2.setEmail("jack@hotmail.com");

77. bean2.setGender("male");

78. list.add(bean2);

79.

80. User bean3 = new User();

81. bean3.setId(1003);

82. bean3.setName("Marry");

83. bean3.setEmail("marry@163.com");

84. bean3.setGender("female");

85. list.add(bean3);

86.

87. User bean4 = new User();

88. bean4.setId(1004);

89. bean4.setName("Linda");

90. bean4.setEmail("linda@21cn.com");

91. bean4.setGender("female");

92. list.add(bean4);

93. }

94. }

把该Servlet 部署到Tomcat 下,在浏览器输入接口地址

http://localhost:8080/article/JSONDemoServlet,输出结果如下:

[{"id":1001,"email":"tony@toeach.net","name":"Tony","gender":"male"},{"id":1002,"email":"jack@hotmail.

com","name":"Jack","gender":"male"},{"id":1003,"email":"marry@163.com","name":"Marry","gender":"fe

male"},{"id":1004,"email":"linda@21cn.com","name":"Linda","gender":"female"}]

2、手机客户端程序

准备好服务端的接口后,接下来就是准备写客户端的程序了。打开Eclipse 新建一个Android 项目。我

们创建一个名为MainActivity 的Activity 类,如下图所示:

因为要访问外部网络,所以要在AndroidManifest.xml 文件里增加一行安全许可:

<uses-permission android:name="android.permission.INTERNET"/>

这样我们的应用程序就可以访问网络了。

接着修改布局文件res\layout\main.xml,增加一个TextView 对象,用来显示解析后的用户数据。

view plaincopy to clipboardprint?

1. <?xml version="1.0" encoding="utf-8"?>

2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/

android"

3. android:orientation="vertical"

4. android:layout_width="fill_parent"

5. android:layout_height="fill_parent">

6. <TextView android:id="@+id/textView"

7. android:layout_width="fill_parent"

8. android:layout_height="fill_parent"/>

9. </LinearLayout>

Android SDK 提供了Apache 的HttpClient 类处理网络访问,相信很多读者朋友都在其他项目当中用

到过HttpClient。我写了一个方法,获取某一网址的网页内容,代码如下:

view plaincopy to clipboardprint?

1. /**

2. * 获取网址内容

3. * @param url

4. * @return

5. * @throws Exception

6. */

7. private String getContent(String url) throws Exception{

8. StringBuilder sb = new StringBuilder();

9.

10. HttpClient client = new DefaultHttpClient();

11. HttpParams httpParams = client.getParams();

12. //设置网络超时参数

13. HttpConnectionParams.setConnectionTimeout(httpParams, 3000);

14. HttpConnectionParams.setSoTimeout(httpParams, 5000);

15. HttpResponse response = client.execute(new HttpGet(url));

16. HttpEntity entity = response.getEntity();

17. if (entity != null) {

18. BufferedReader reader = new BufferedReader(new InputStrea

mReader(entity.getContent(), "UTF-8"), 8192);

19.

20. String line = null;

21. while ((line = reader.readLine())!= null){

22. sb.append(line + "\n");

23. }

24. reader.close();

25. }

26. return sb.toString();

27. }

修改MainActivity.java,在onCreate 方法里增加解析服务端接口内容的代码,如下所示:

view plaincopy to clipboardprint?

1. @Override

2. public void onCreate(Bundle savedInstanceState) {

3. super.onCreate(savedInstanceState);

4. setContentView(R.layout.main);

5.

6. try{

7. StringBuffer sb = new StringBuffer();

8. //在测试过程中,经常是用本机做测试服务器,访问本机的IP 地址要设置为

10.0.2.2

9. String url = "http://10.0.2.2:8080/article/JSONDemoServlet";

10. String body = getContent(url);

11. JSONArray array = new JSONArray(body);

12. for(int i=0; i<array.length(); i++){

13. JSONObject obj = array.getJSONObject(i);

14. sb.append("id:").append(obj.getInt("id")).append("\t");

15. sb.append("name:").append(obj.getString("name")).append("

\r\n");

16. sb.append("gender:").append(obj.getString("gender")).appen

d("\t");

17. sb.append("email:").append(obj.getString("email")).append("

\r\n");

18. sb.append("----------------------\r\n");

19. }

20. TextView textView = (TextView)findViewById(R.id.textView);

21. textView.setText(sb.toString());

22. }catch(Exception e){}

23. }

运行后的界面如下图:


图4.运行界面

总结

本文简单介绍了JSON 的相关知识,以及在Android 平台中如何通过JSON 来和服务端的应用进行数

据交换。

作者介绍

万云,广州盈哲计算机科技有限公司技术总监。拥有10 年以上的软件开发经验,擅长J2EE、大型

网站、移动增值服务等领域的技术开发。


0 0
原创粉丝点击