【Android】JSONObject和Gson的使用

三三要成为安卓糕手

一: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. 定义接口(如ApiServicegetUserInfo(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. 定义接口(如ApiServicelogin(@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. 多接口场景下代码仍需重复构建RequestCallback 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. 追求代码可维护性和类型安全
相关推荐
万行7 小时前
点评项目(Redis中间件)&第二部分Redis基础
java·数据库·redis·spring·中间件
Rysxt_7 小时前
Git 合并与变基详解及 IntelliJ IDEA 实战指南
java·git·intellij-idea
csdn_aspnet7 小时前
IDEA 中创建 Springboot 项目没有 Java8 选项的解决办法
java·spring boot·intellij-idea
YA3338 小时前
java设计模式一、单例模式
java·单例模式·设计模式
计算机学姐8 小时前
基于SpringBoot的运动服装销售系统【2026最新】
java·vue.js·spring boot·后端·spring·tomcat·mybatis
葵野寺8 小时前
【RelayMQ】基于 Java 实现轻量级消息队列(五)
java·开发语言·java-rabbitmq
COTAS9 小时前
K8S 知识框架和命令操作
java·容器·kubernetes
duration~9 小时前
SpringAI模型评估
java·spring boot·spring·ai编程
叫我阿柒啊10 小时前
从Java全栈开发到微服务架构:一次真实的面试实录
java·微服务·vue3·springboot·前端开发·后端开发·项目经验