目标
在Android客户端通过网络访问、解析Json数据。
从Tomcat服务器获取Json数据,然后在日志中打印出来。
一、JSON概述
JSON数据格式的定义
JSON的全称:JavaScript Object Notation,是一种轻量级的数据交换格式。
Json建构于两种结构:
一种是以 (key/value)对形式存在的无序的jsonObject对象,一个对象以“{”(左花括号)开始,“}”(右花括号)结束。
每个“名称”后跟一个“:”(冒号);“‘名称/值’ 对”之间使用“,”(逗号)分隔。
例如:{ "name": "张三", "age":20 }, 这就是一个最简单的json对象,对于这种数据格式,key值必须要是string类型,而对于value,则可以是string、number、object、array等数据类型:
另一种数据格式就是有序的value的集合,这种形式被称为是jsonArray,数组是值(value)的有序集合。一个数组以“[”(左中括号)开始,“]”(右中括号)结束。值之间使用“,”(逗号)分隔。
如:[{"age":20,"name":"张三0"},{"age":21,"name":"张三1"},{"age":22,"name":"张三2"},{"age":23,"name":"张三3"},{"age":24,"name":"张三4"}]
或者
{ “students” : [{"age":20,"name":"张三0"},{"age":21,"name":"张三1"},{"age":22,"name":"张三2"},{"age":23,"name":"张三3"},{"age":24,"name":"张三4"}] }
二、准备工作
首先,声明一个 User 类
package com.sdbi.bean; public class User { private String name; private int age; public User() { } public User(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
其次,编写一个工具类,访问Tomcat上的Web服务来获取Json字符串。
package com.sdbi.http; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; public class HttpUtils { public static String getJsonContent(String url_path) { try { URL url = new URL(url_path); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setConnectTimeout(3000); connection.setRequestMethod("GET");//请求方法 connection.setDoInput(true);//输入流 int code = connection.getResponseCode(); if (code == 200) { //服务器已准备好,可以取出流,流直接转换成字符串 return ChangeInputStream(connection.getInputStream()); } } catch (Exception e) { e.printStackTrace(); } return ""; } private static String ChangeInputStream(InputStream inputStream) { String jsonString = ""; //字节数组流,表示在内存地址当中可以显示出来,可以把数据写入内存当中 ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); int len = 0; byte[] data = new byte[1024]; try { while ((len = inputStream.read(data)) != -1) { outputStream.write(data, 0, len); } //outputStream流——>写入ByteArrayOutputStream——>转换成字节数组 jsonString = new String(outputStream.toByteArray()); } catch (IOException e) { e.printStackTrace(); } return jsonString; } }
三、解析Json数据格式
这里将使用两种json的解析库来对我们的json数据格式进行解析以及生成我们的json数据格式。
【名词解释】
- Serialization:序列化,使Java对象到Json字符串的过程。
- Deserialization:反序列化,Json字符串转换成Java对象。
1、Android原生JSON解析方式
我们最常用的两个类就是JSONObject和JSONArray这两个类,分别代表了json对象和json数组,这两个类都实现了 JSON 这个接口,下面我们通过几个小例子来看看如何将我们常见的几种数据格式转换成我们的json对象(我们一般称之为JSON数据的序列化)以及再将json对象在转换成我们的数据格式(称之为反序列化)。
Json解析工具类JsonTools.java
package com.sdbi.json; import com.sdbi.bean.User; import org.json.JSONArray; import org.json.JSONObject; import java.util.ArrayList; public class JsonTools { /** * 原生的JSON解析方式,数组包含多个对象 * Json形式:[{"age":20,"name":"张三0"},{"age":21,"name":"张三1"},{"age":22,"name":"张三2"},{"age":23,"name":"张三3"}] * @param jsonString * @return 用户list */ public static ArrayList<User> getUserListByJsonArray(String jsonString) { ArrayList<User> list = new ArrayList<>(); try { JSONArray jsonArray = new JSONArray(jsonString); for (int i = 0; i < jsonArray.length(); i++) { JSONObject jsonObject = jsonArray.getJSONObject(i); User user = new User((String) jsonObject.get("name"), (int) jsonObject.get("age")); list.add(user); } } catch (Exception e) { e.printStackTrace(); } return list; } /** * 原生的JSON解析方式,单个对象(未测试) * Json形式: * @param jsonString * @return 用户对象 */ public static User getUserByJsonObject(String jsonString) { User user = null; try { JSONObject jsonObject = new JSONObject(jsonString); user = new User((String) jsonObject.get("name"), (int) jsonObject.get("age")); } catch (Exception e) { e.printStackTrace(); } return user; } }
MainActivity.java
package com.sdbi.jsontest; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.TextView; import androidx.appcompat.app.AppCompatActivity; import com.sdbi.bean.User; import com.sdbi.http.HttpUtils; import com.sdbi.json.JsonTools; import java.util.ArrayList; public class MainActivity extends AppCompatActivity implements View.OnClickListener { private Button btnQuery; private TextView tvInfo; private String path = "http://192.168.3.139:8081/JsonServer/JsonServlet"; private static final String TAG = "MainActivity"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btnQuery = (Button) findViewById(R.id.btnQuery); btnQuery.setOnClickListener(this); tvInfo = findViewById(R.id.tvInfo); } @Override public void onClick(View view) { switch (view.getId()) { case R.id.btnQuery: new Thread(new Runnable() { @Override public void run() { Message message = new Message(); message.what = 1; String jsonString = HttpUtils.getJsonContent(path); Log.d(TAG, "子线程:" + jsonString); message.obj = jsonString; handler.sendMessage(message); } }).start(); break; } } private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case 1: String json = (String) msg.obj; Log.d(TAG, "主线程:" + json); tvInfo.setText(json); ArrayList<User> arrayList = JsonTools.getUserListByJsonArray(json); Log.d(TAG, "handleMessage: 用户数:" + arrayList.size()); break; } } }; }
2、Google提供的GSON解析方式
-
提供一种像toString()和构造方法的很简单的机制,来实现Java 对象和Json之间的互相转换。
-
允许已经存在的无法改变的对象,转换成Json,或者Json转换成已存在的对象。
-
允许自定义对象的表现形式
-
支持任意的复杂对象
-
能够生成可压缩和可读的Json的字符串输出。
(1)配置gson依赖,build.gradle(:app)文件
dependencies {
implementation 'com.google.code.gson:gson:2.8.8'
}
(2)反序列化Json,JsonTools.java
package com.sdbi.json; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import com.sdbi.bean.User; import org.json.JSONArray; import org.json.JSONObject; import java.util.ArrayList; import java.util.List; public class JsonTools { ...... /** * Google的GSON解析方式,数组包含多个对象 * * Json形式:[{"age":20,"name":"张三0"},{"age":21,"name":"张三1"},{"age":22,"name":"张三2"},{"age":23,"name":"张三3"}] * @param jsonString * @return 用户list */ public static ArrayList<User> getUserListByGson(String jsonString) { ArrayList<User> list = new ArrayList<>(); try { Gson gson = new Gson(); list = gson.fromJson(jsonString, new TypeToken<ArrayList<User>>() {}.getType()); } catch (Exception e) { e.printStackTrace(); } return list; } }
(3)调用Gson的解析方法
package com.sdbi.jsontest; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.TextView; import androidx.appcompat.app.AppCompatActivity; import com.sdbi.bean.User; import com.sdbi.http.HttpUtils; import com.sdbi.json.JsonTools; import java.util.ArrayList; public class MainActivity extends AppCompatActivity implements View.OnClickListener { ...... private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case 1: String json = (String) msg.obj; Log.d(TAG, "主线程:" + json); tvInfo.setText(json); // ArrayList<User> arrayList = JsonTools.getUserListByJsonArray(json); ArrayList<User> arrayList = JsonTools.getUserListByGson(json);// 换成调用Gson的方式解析 Log.d(TAG, "handleMessage: 用户数:" + arrayList.size()); break; } } }; }
3、阿里提供的FastJson解析方式
FastJson是一个Java语言编写的JSON处理器,由阿里巴巴公司开发。(1)配置fastjson依赖,build.gradle(:app)文件
dependencies { implementation 'com.alibaba:fastjson:1.2.78'
}
(2)反序列化Json,JsonTools.java
package com.sdbi.json;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.sdbi.bean.User;
import org.json.JSONArray;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
public class JsonTools {
......
/**
* 阿里的FastJson解析方式,数组包含多个对象
* * Json形式:[{"age":20,"name":"张三0"},{"age":21,"name":"张三1"},{"age":22,"name":"张三2"},{"age":23,"name":"张三3"}]
* @param jsonString
* @return 用户list
*/
public static ArrayList<User> getUserListByFastJson(String jsonString) {
if (TextUtils.isEmpty(jsonString)) {
return null;
}
ArrayList<User> list = new ArrayList<>();
try {
list = parseObject(jsonString,new TypeReference<ArrayList<User>>(){});
} catch (Exception e) {
e.printStackTrace();
}
return list;
}
}
(3)调用FastJson的解析方法
package com.sdbi.jsontest;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import com.sdbi.bean.User;
import com.sdbi.http.HttpUtils;
import com.sdbi.json.JsonTools;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
......
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
String json = (String) msg.obj;
Log.d(TAG, "主线程:" + json);
tvInfo.setText(json);
ArrayList<User> arrayList = JsonTools.getUserListByFastJson(json);// 换成调用FastJson的方式解析
Log.d(TAG, "handleMessage: 用户数:" + arrayList.size());
break;
}
}
};
}