
三三要成为安卓糕手
一:JSONObject介绍
JSON常见格式
json
{
"name": "Alice",
"age": 30,
"isStudent": false,
"address": {
"city": "New York",
"zip": "10001"
},
"courses": ["Math", "Science", "History"],
"grades": [85, 90, 92],
"graduated": null
}
1:利用创建Json数据
java
/**
* 使用JSONObject完成json数据的创建
*
* {
* "name": "Alice",
* "age": 30,
* "isStudent": false,
* "address": {
* "city": "New York",
* "zip": "10001"
* },
* "courses": ["Math", "Science", "History"],
* "grades": [85, 90, 92],
* "graduated": null
* }
*/
private void createJSON(){
JSONObject jsonObject = new JSONObject();
try {
//放一些常规的key_value值
jsonObject.put("name","Alice");
jsonObject.put("age",30);
jsonObject.put("isStudent", false);
//嵌套一个JSON对象
JSONObject addressJSON = new JSONObject();
addressJSON.put("city","New York");
addressJSON.put("zip" , "10001");
jsonObject.put("address" , addressJSON);
//放一个json数组,类型为string
JSONArray course = new JSONArray();
course.put("Math");
course.put("Science");
course.put("History");
jsonObject.put("courses",course);
//放一个json数组,类型为int
JSONArray grades = new JSONArray();
grades.put(85);
grades.put(90);
grades.put(92);
jsonObject.put("grades",grades);
jsonObject.put("graduated",null);
//把得到的JSON转化为字符串,打印日志查看效果
String string = jsonObject.toString();
Log.i(TAG, "createJSON: " + string);
} catch (JSONException e) {
throw new RuntimeException(e);
}
}
-
put方法放键值对:Json本来就是键值对的形式,所以这里对类型没有要求
-
放一个对象:其实就是一个Json嵌套一个Json
-
放Json数组:这里实例化的对象是JSONArray(),然后put方法往里面放就行了
-
转化为字符串:用toString()方法即可
2:获取JSON中的属性
java
private void getJSON(){
String json = "{\"name\":\"Alice\",\"age\":30,\"isStudent\":false,\"address\":{\"city\":\"New York\",\"zip\":\"10001\"},\"courses\":[\"Math\",\"Science\",\"History\"],\"grades\":[85,90,92]}";
//
try {
JSONObject jsonObject = new JSONObject(json);
//想获取key对应的value,就要用对应类型的get方法
String name = jsonObject.getString("name");
Log.i(TAG, "getJSON: name =" + name);
int age = jsonObject.getInt("age");
Log.i(TAG, "getJSON: age = " + age);
boolean isStudent = jsonObject.getBoolean("isStudent");
Log.i(TAG, "getJSON: isStudent = " + isStudent);
JSONObject addressObject = jsonObject.getJSONObject("address");
String city = addressObject.getString("city");
Log.i(TAG, "getJSON: city = " + city);
JSONArray coursesArray = jsonObject.getJSONArray("courses");
String course0 = coursesArray.getString(0);
Log.i(TAG, "getJSON: 第一个课程是"+course0);
// String string = jsonObject.getString("graduated");
// Log.i(TAG, "getJSON: "+string);
} catch (JSONException e) {
throw new RuntimeException(e);
}
}
- 实例化JSONObject的时候需要传入JSON字符串
- 想获取key对应的value,就要用对应类型的get方法
二:Gson介绍
1:依赖
java
implementation ("com.google.code.gson:gson:2.11.0")
Gson 是 Google 开发的一个 Java 库,主要用于在 Java 对象和 JSON 数据之间进行相互转换,它提供了简单易用的 API 来处理 JSON 序列化(将 Java 对象转为 JSON 字符串)和反序列化(将 JSON 字符串转为 Java 对象)操作。

2:利用Gson创建JSON字符串
java
private void gsonCreateJSON(){
//创建Student对象
Student student = new Student();
student.setName("老龙");
student.setAge(19);
student.setStudent(true);
Student.Address address = new Student.Address();
address.setCity("新疆");
address.setZip("798");
student.setAddress(address);
student.setCourses(new String[]{"数学","计算机与科学"});
student.setGrades(new Integer[]{100,120});
//转化为JSON字符串
Gson gson = new Gson();
String json = gson.toJson(student);
Log.i(TAG, "gsonCreateJSON: " + json);
}
效果如下:

3:利用Gson获取JSON中的属性
java
private void gsonGetJSON(){
String json = "{\"address\":{\"city\":\"新疆\",\"zip\":\"798\"},\"age\":19,\"courses\":[\"数学\",\"计算机与科学\"],\"grades\":[100,120],\"isStudent\":true,\"name\":\"老龙\"}";
//相当于把这个JSON字符串解析java对象,在通过get方法获取内部的数据
Gson gson = new Gson();
Student student = gson.fromJson(json, Student.class);
String name = student.getName();
Integer[] grades = student.getGrades();
Log.i(TAG, "gsonCreateJSON: name = " + name);
Log.i(TAG, "gsonCreateJSON: grades[1] = " + grades[1])
}
优化:之前在http,封装json请求体时就可以创建一个实体类,解析成一个json字符串

注意:解析字符串的时候不要带多余的东西

三:安卓网络通信总结
对比维度 | JSONObject | HttpUrlConnection | OkHttp | Retrofit2 |
---|---|---|---|---|
核心功能定位 | Android 原生 JSON 解析 / 构建工具,仅处理 JSON 数据(无 HTTP 能力) | Java 原生 HTTP 通信工具,用于发起 HTTP 请求 / 接收响应,需手动处理 JSON 和线程 | 第三方 HTTP 客户端(Square 开发),封装 HttpUrlConnection,简化 HTTP 操作 | 基于 OkHttp 的 RESTful API 框架,通过注解 + 接口化方式封装 HTTP 请求,自动处理 JSON 序列化 / 反序列化 |
JSON 处理能力 | ||||
- 解析 JSON(从字符串到对象) | 需手动调用getXXX() 方法(如getString("name") 、getJSONObject("address") ),嵌套结构需逐层解析(见getJSON() 方法),无类型安全 |
仅接收 HTTP 响应的 JSON 字符串,需依赖第三方库(如 Gson)手动解析(代码中未体现,需额外处理) | 仅接收 HTTP 响应的 JSON 字符串,需依赖 Gson 手动调用fromJson() 解析(见sendPostRequest() 中ResLogin resLogin = new Gson().fromJson(json, ResLogin.class) ) |
集成GsonConverterFactory 后,自动将 JSON 响应解析为指定 JavaBean(如UserInfoQuery ),无需手动调用 Gson(见sendGetRequest() 中直接获取response.body().getData().getUser().getNickname() ) |
- 构建 JSON(从对象到字符串) | 需手动调用put() 方法(如jsonObject.put("name","Alice") ),嵌套对象 / 数组需手动创建JSONObject /JSONArray (见createJSON() 方法) |
需手动拼接 JSON 字符串(如"{ \"account\": \"" + account + "\",\"password\": \"" + password + "\" }" ),易出错 |
依赖 Gson 调用toJson() 将 JavaBean(如ReqLogin )转为 JSON 字符串(见sendPostRequest() 中new Gson().toJson(new ReqLogin(account, password)) ) |
自动将 JavaBean(如ReqLogin )序列化为 JSON 请求体,无需手动处理(仅需在接口方法中传入 JavaBean 参数) |
- 类型安全 | 无,需手动判断数据类型(如getInt("age") 若字段为字符串会抛异常) |
无,JSON 字符串解析需手动保证类型匹配 | 依赖 Gson 实现类型安全,但需手动指定目标类 | 完全类型安全,接口方法返回值直接指定响应 JavaBean 类型(如Call<UserInfoQuery> ) |
GET 请求实现 | ||||
- 核心步骤 | 无 HTTP 能力,无法发起 GET 请求 | 1. 手动创建URL 对象; 2. 调用openConnection() 获取HttpURLConnection ; 3. 手动设置请求方法(setRequestMethod("GET") )、超时时间; 4. 手动获取InputStream ,通过BufferedReader 读取响应; 5. 手动关闭连接(见sendGetRequest() 方法) |
1. 构建OkHttpClient (可配置超时); 2. 构建Request 对象(指定 URL 和GET 方法); 3. 调用okHttpClient.newCall(request) 获取Call ; 4. 调用enqueue() 异步执行,在Callback 中处理响应(见sendGetRequest() 方法) |
1. 构建Retrofit (指定 BaseURL 和转换器); 2. 定义接口(如ApiService 的getUserInfo(String userId, String type) ),用@GET 注解指定接口路径和参数; 3. 调用接口方法获取Call ; 4. 调用enqueue() 处理响应(见sendGetRequest() 方法) |
- 线程处理 | 无 | 需手动创建子线程(new Thread(new Runnable() { ... }) ),更新 UI 需手动调用runOnUiThread() |
自动在子线程执行请求,Callback 回调在子线程,更新 UI 需手动调用runOnUiThread() |
自动在子线程执行请求,Callback 回调在子线程,更新 UI 需手动调用runOnUiThread() (代码中Toast 直接调用,因onResponse 已在主线程?实际 Retrofit 默认回调在子线程,代码中可能简化处理) |
- 参数拼接 | 无 | 需手动拼接 URL 参数(如"http://...?user_id=" + id + "&type=archives" ) |
需手动拼接 URL 参数(同 HttpUrlConnection)或通过HttpUrl.Builder 构建 URL |
自动拼接参数:通过@Query 注解(如getUserInfo(@Query("user_id") String userId, @Query("type") String type) ),无需手动拼接 |
POST 请求实现 | ||||
- 核心步骤 | 无 HTTP 能力,无法发起 POST 请求 | 1. 同 GET 步骤 1-3,额外设置setDoOutput(true) 允许输出请求体; 2. 手动设置请求头(Content-Type: application/json ); 3. 手动获取OutputStream ,写入 JSON 字符串; 4. 同 GET 步骤 4-5(见SendPostRequest() 方法) |
1. 同 GET 步骤 1; 2. 构建RequestBody (指定 JSON 媒体类型和 JSON 字符串); 3. 构建Request 对象(指定 URL 和post(requestBody) ); 4. 同 GET 步骤 3-4(见sendPostRequest() 方法) |
1. 同 GET 步骤 1; 2. 定义接口(如ApiService 的login(@Body ReqLogin reqLogin) ),用@POST 注解指定路径,@Body 指定请求体; 3. 同 GET 步骤 3-4(见sendPostRequest() 方法) |
- 请求体处理 | 无 | 需手动拼接 JSON 字符串并转为字节流写入(易出错,如引号转义) | 需手动将 JavaBean 转为 JSON 字符串,再封装为RequestBody |
自动将@Body 注解的 JavaBean(如ReqLogin )转为 JSON 请求体,无需手动处理 |
- 响应处理 | 无 | 手动读取响应流,需手动解析 JSON 字符串 | 在Callback 中读取response.body().string() ,再手动用 Gson 解析 |
在Callback 中直接获取response.body() (已自动解析为 JavaBean) |
优缺点 | ||||
- 优点 | 1. 原生 API,无需依赖第三方库; 2. 轻量,仅处理 JSON 时性能开销小 | 1. 原生 API,无需依赖第三方库; 2. 完全可控,可自定义所有 HTTP 细节 | 1. 封装完善,简化 HTTP 操作(如自动处理连接池、重定向); 2. 支持同步 / 异步请求; 3. 内置超时、拦截器等实用功能 | 1. 接口化编程,代码结构清晰(分离 API 定义和实现); 2. 自动处理 JSON 序列化 / 反序列化; 3. 支持多种转换器(Gson、Jackson 等); 4. 支持 RxJava、协程等异步框架 |
- 缺点 | 1. 无 HTTP 能力,需配合其他工具使用; 2. 手动解析 / 构建 JSON 代码繁琐,易出错; 3. 无类型安全 | 1. 代码冗余(手动处理流、线程、参数拼接); 2. 无默认 JSON 处理,需额外集成; 3. 不支持连接池,性能较差 | 1. 仍需手动处理 JSON 序列化 / 反序列化(依赖 Gson); 2. 多接口场景下代码仍需重复构建Request 和Callback |
1. 依赖 Retrofit+OkHttp + 转换器,包体积较大; 2. 简单请求场景下配置稍复杂; 3. 灵活性较低(复杂 HTTP 场景需自定义拦截器) |
适用场景 | 1. 仅需单独处理 JSON 数据(如本地 JSON 字符串解析 / 构建); 2. 轻量级场景,不依赖第三方库 | 1. 学习 HTTP 原理(理解底层流程); 2. 极简场景,不允许引入第三方库; 3. 对 HTTP 细节有高度自定义需求 | 1. 需简化 HTTP 操作,但无需接口化封装的场景; 2. 需灵活处理 HTTP 细节(如自定义拦截器、请求头); 3. 中小型项目的网络请求 | 1. 大型项目,需统一管理 API 接口; 2. RESTful API 场景,需规范请求格式; 3. 需集成 RxJava / 协程实现复杂异步逻辑; 4. 追求代码可维护性和类型安全 |