Android访问网络解析Json数据
目标
在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字符串。
本例是使用的HttpURLConnection的方式来进行网络访问的。通过HttpURLConnection进行HTTP操作可以适用于大多数的应用程序。
虽然HttpURLConnection的API提供的比较简单,但是同时这也使得我们可以更加容易地去使用和扩展它。
继承至URLConnection,抽象类,无法直接实例化对象。通过调用openCollection() 方法获得对象实例,默认是带gzip压缩的。
HttpURLConnection的使用步骤
- 创建一个URL对象: URL url = new URL("https://www.baidu.com");
- 调用URL对象的openConnection( )来获取HttpURLConnection对象实例: HttpURLConnection connection = (HttpURLConnection) url.openConnection();
- 设置HTTP请求使用的方法:GET或者POST,或者其他请求方式比如:connection.setRequestMethod("GET");
- 设置连接超时,读取超时的毫秒数,以及服务器希望得到的一些消息头: connection.setConnectTimeout(6 * 1000); connection.setReadTimeout(6 * 1000);
- 获取响应代码做判断:connection.getResponseCode();
- 调用getInputStream()方法获得服务器返回的输入流,然后输入流进行读取了 InputStream in = connection.getInputStream();
- 最后调用disconnect()方法将HTTP连接关掉 connection.disconnect();
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;
}
}
};
}
四、使用ListView展示数据
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了