当前位置: 首页 > news >正文

《Android 应用开发基础教程》——第十章:使用 Gson 实现网络 JSON 数据解析与对象映射

目录

第十章:使用 Gson 实现网络 JSON 数据解析与对象映射

🔹 10.1 什么是 Gson?

🔸 10.2 添加依赖

🔸 10.3 基础使用

✦ 示例 JSON 字符串:

✦ 定义对应的 Java 类:

✦ JSON ➜ 对象(反序列化):

✦ 对象 ➜ JSON(序列化):

🔸 10.4 解析 JSON 数组

✦ 示例 JSON 数组:

✦ Java 代码解析(使用 TypeToken):

🔸 10.5 配合 OkHttp 实战应用

✦ 示例:请求服务器返回 JSON,并转换成对象

✦ 示例实体类 Post:

✅ 小技巧与注意事项

🧪 实战练习建议

习题答案

项目结构

1. MainActivity.java

2. NewsAdapter.java

3. NewsItem.java

4. GsonUtils.java

5. activity_main.xml

6. item_news.xml

总结


第十章:使用 Gson 实现网络 JSON 数据解析与对象映射

        在进行网络请求时,服务器返回的数据大多是 JSON 格式。手动解析 JSON 字符串非常繁琐,因此我们通常使用第三方库如 Gson 来将 JSON 数据自动转为 Java 对象,方便开发与维护。


🔹 10.1 什么是 Gson?

Gson 是 Google 提供的 JSON 库,能轻松实现:

  • JSON ➜ Java 对象(反序列化)

  • Java 对象 ➜ JSON 字符串(序列化)


🔸 10.2 添加依赖

build.gradle 文件中添加:

implementation 'com.google.code.gson:gson:2.10.1'


🔸 10.3 基础使用

✦ 示例 JSON 字符串:

{"id": 1,"title": "Gson 教程","author": "Alice"
}


✦ 定义对应的 Java 类:

public class Article {private int id;private String title;private String author;// Getter/Setter 省略,可使用 Lombok 自动生成
}


✦ JSON ➜ 对象(反序列化):

String json = "{\"id\":1,\"title\":\"Gson 教程\",\"author\":\"Alice\"}";Gson gson = new Gson();
Article article = gson.fromJson(json, Article.class);Log.d("GSON", "标题:" + article.getTitle());


✦ 对象 ➜ JSON(序列化):

Article article = new Article();
article.setId(2);
article.setTitle("新文章");
article.setAuthor("Bob");String json = gson.toJson(article);
Log.d("GSON", "JSON字符串:" + json);


🔸 10.4 解析 JSON 数组

✦ 示例 JSON 数组:

[{"id": 1, "title": "A"},{"id": 2, "title": "B"}
]


✦ Java 代码解析(使用 TypeToken):

String jsonArray = "[{\"id\":1,\"title\":\"A\"},{\"id\":2,\"title\":\"B\"}]";Type listType = new TypeToken<List<Article>>(){}.getType();
List<Article> articles = new Gson().fromJson(jsonArray, listType);for (Article a : articles) {Log.d("GSON", a.getTitle());
}


🔸 10.5 配合 OkHttp 实战应用

✦ 示例:请求服务器返回 JSON,并转换成对象

OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url("https://jsonplaceholder.typicode.com/posts/1").build();client.newCall(request).enqueue(new Callback() {@Overridepublic void onFailure(Call call, IOException e) {e.printStackTrace();}@Overridepublic void onResponse(Call call, Response response) throws IOException {String json = response.body().string();// 解析 JSON 到 Java 对象Gson gson = new Gson();Post post = gson.fromJson(json, Post.class);Log.d("GSON", "标题:" + post.getTitle());}
});


✦ 示例实体类 Post

public class Post {private int userId;private int id;private String title;private String body;// Getter 和 Setter
}


✅ 小技巧与注意事项

问题建议
字段名不一致@SerializedName("json字段") 标注
多层嵌套 JSON创建多个内部类解析
忽略某些字段使用 transient@Expose 注解

🧪 实战练习建议

  1. 请求网络中的新闻 JSON,并展示在 RecyclerView

  2. 把用户输入保存为对象,用 Gson 写入本地文件或 SharedPreferences

  3. 写一个工具类封装 GsonUtils,实现常规解析函数


📢 下一章预告:

第十一章:Android 中的图片加载与缓存(Glide 使用详解)


习题答案

项目结构

MainActivity.java
NewsAdapter.java
GsonUtils.java
activity_main.xml
item_news.xml

1. MainActivity.java

package com.example.demo;import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.json.JSONArray;
import org.json.JSONObject;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;public class MainActivity extends AppCompatActivity {private RecyclerView recyclerView;private NewsAdapter adapter;private List<NewsItem> newsList;private OkHttpClient client;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);recyclerView = findViewById(R.id.recyclerView);recyclerView.setLayoutManager(new LinearLayoutManager(this));newsList = new ArrayList<>();adapter = new NewsAdapter(newsList);recyclerView.setAdapter(adapter);client = new OkHttpClient();fetchNewsData();}private void fetchNewsData() {String url = "https://newsapi.org/v2/top-headlines?country=us&apiKey=YOUR_API_KEY"; // 替换为你的 API 密钥Request request = new Request.Builder().url(url).build();client.newCall(request).enqueue(new Callback() {@Overridepublic void onFailure(Call call, IOException e) {runOnUiThread(() -> adapter.updateData(new ArrayList<>()));}@Overridepublic void onResponse(Call call, Response response) throws IOException {if (response.isSuccessful()) {try {String responseData = response.body().string();JSONObject jsonObject = new JSONObject(responseData);JSONArray articles = jsonObject.getJSONArray("articles");List<NewsItem> newsItems = new ArrayList<>();for (int i = 0; i < articles.length(); i++) {JSONObject article = articles.getJSONObject(i);String title = article.getString("title");String description = article.getString("description");newsItems.add(new NewsItem(title, description));}runOnUiThread(() -> adapter.updateData(newsItems));} catch (Exception e) {e.printStackTrace();runOnUiThread(() -> adapter.updateData(new ArrayList<>()));}} else {runOnUiThread(() -> adapter.updateData(new ArrayList<>()));}}});}
}

2. NewsAdapter.java

package com.example.demo;import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;public class NewsAdapter extends RecyclerView.Adapter<NewsAdapter.ViewHolder> {private List<NewsItem> newsList;public NewsAdapter(List<NewsItem> newsList) {this.newsList = newsList;}@NonNull@Overridepublic ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_news, parent, false);return new ViewHolder(view);}@Overridepublic void onBindViewHolder(@NonNull ViewHolder holder, int position) {NewsItem item = newsList.get(position);holder.textViewTitle.setText(item.getTitle());holder.textViewDescription.setText(item.getDescription());}@Overridepublic int getItemCount() {return newsList.size();}public void updateData(List<NewsItem> newData) {newsList.clear();newsList.addAll(newData);notifyDataSetChanged();}public static class ViewHolder extends RecyclerView.ViewHolder {TextView textViewTitle;TextView textViewDescription;public ViewHolder(@NonNull View itemView) {super(itemView);textViewTitle = itemView.findViewById(R.id.textViewTitle);textViewDescription = itemView.findViewById(R.id.textViewDescription);}}
}

3. NewsItem.java

package com.example.demo;public class NewsItem {private String title;private String description;public NewsItem(String title, String description) {this.title = title;this.description = description;}public String getTitle() {return title;}public String getDescription() {return description;}
}

4. GsonUtils.java

package com.example.demo;import android.content.Context;
import android.content.SharedPreferences;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Type;
import java.util.List;public class GsonUtils {private static final Gson gson = new Gson();// 将对象写入 SharedPreferencespublic static void saveObjectToSharedPreferences(Context context, String key, Object object) {SharedPreferences sharedPreferences = context.getSharedPreferences("app_prefs", Context.MODE_PRIVATE);String json = gson.toJson(object);sharedPreferences.edit().putString(key, json).apply();}// 从 SharedPreferences 读取对象public static <T> T getObjectFromSharedPreferences(Context context, String key, Class<T> classOfT) {SharedPreferences sharedPreferences = context.getSharedPreferences("app_prefs", Context.MODE_PRIVATE);String json = sharedPreferences.getString(key, null);return json == null ? null : gson.fromJson(json, classOfT);}// 将对象写入本地文件public static void saveObjectToFile(Context context, String fileName, Object object) {try (FileOutputStream fos = context.openFileOutput(fileName, Context.MODE_PRIVATE)) {String json = gson.toJson(object);fos.write(json.getBytes());} catch (Exception e) {e.printStackTrace();}}// 从本地文件读取对象public static <T> T getObjectFromFile(Context context, String fileName, Class<T> classOfT) {try (FileInputStream fis = context.openFileInput(fileName);BufferedReader reader = new BufferedReader(new InputStreamReader(fis))) {StringBuilder json = new StringBuilder();String line;while ((line = reader.readLine()) != null) {json.append(line);}return gson.fromJson(json.toString(), classOfT);} catch (Exception e) {e.printStackTrace();return null;}}// 将列表写入本地文件public static <T> void saveListToFile(Context context, String fileName, List<T> list) {Type type = new TypeToken<List<T>>() {}.getType();try (FileOutputStream fos = context.openFileOutput(fileName, Context.MODE_PRIVATE)) {String json = gson.toJson(list, type);fos.write(json.getBytes());} catch (Exception e) {e.printStackTrace();}}// 从本地文件读取列表public static <T> List<T> getListFromFile(Context context, String fileName, Type type) {try (FileInputStream fis = context.openFileInput(fileName);BufferedReader reader = new BufferedReader(new InputStreamReader(fis))) {StringBuilder json = new StringBuilder();String line;while ((line = reader.readLine()) != null) {json.append(line);}return gson.fromJson(json.toString(), type);} catch (Exception e) {e.printStackTrace();return null;}}
}

5. activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/recyclerView"android:layout_width="match_parent"android:layout_height="match_parent"android:padding="8dp" />
</LinearLayout>

6. item_news.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"android:padding="8dp"><TextViewandroid:id="@+id/textViewTitle"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="Title"android:textSize="18sp"android:textStyle="bold" /><TextViewandroid:id="@+id/textViewDescription"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="Description"android:textSize="14sp" />
</LinearLayout>

总结

  1. 网络请求:通过 OkHttp 获取新闻 JSON 数据并展示在 RecyclerView 中。
  2. 数据存储
    • 使用 GsonUtils 将用户输入的对象保存到本地文件或 SharedPreferences
    • 提供了多种存储和解析方法(如单个对象、列表等)。
  3. 工具类:封装了 GsonUtils,方便复用。

相关文章:

  • RAGFlow报错:ESConnection.sql got exception
  • 纯html实现的json数据转csv文件
  • 题解:洛谷 CF2091E Interesting Ratio
  • 猫,为什么是猫?
  • Y1代码AC集
  • Python协程入门指北
  • 数据结构与算法学习笔记(Acwing提高课)----动态规划·背包模型(一)
  • 奥地利学派方法论的三个基础
  • Python TensorFlow库【深度学习框架】全面讲解与案例
  • 从MCP基础到FastMCP实战应用
  • 安全学习基础入门5集
  • 9. 深入Spring AI:刨析 ChatMemory
  • LeetCode 150题解 | 逆波兰表达式求值
  • WPF使用依赖注入框架AutoMapper
  • 第T10周:数据增强
  • 【MySQL】复合查询与内外连接
  • 日语学习-日语知识点小记-构建基础-JLPT-N4阶段(13): ておきます ています & てあります
  • OpenGL-ES 学习(15) ----纹理
  • 【Unity】 组件库分类详解
  • 【计算机视觉】语义分割:MMSegmentation:OpenMMLab开源语义分割框架实战指南
  • 426.8万人次!长三角铁路创单日客发量历史新高
  • 五一假期上海口岸出入境客流总量预计达59.4万人,同比增约30%
  • 全国人大常委会关于授权国务院在中国(新疆)自由贸易试验区暂时调整适用《中华人民共和国种子法》有关规定的决定
  • 范宇任上海宝山区副区长
  • “五一”假期预计全社会跨区域人员流动量超14亿人次
  • 招商蛇口:一季度营收约204亿元,净利润约4.45亿元