《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 注解 |
🧪 实战练习建议
-
请求网络中的新闻 JSON,并展示在 RecyclerView
-
把用户输入保存为对象,用 Gson 写入本地文件或
SharedPreferences
-
写一个工具类封装
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>
总结
- 网络请求:通过 OkHttp 获取新闻 JSON 数据并展示在
RecyclerView
中。 - 数据存储:
- 使用
GsonUtils
将用户输入的对象保存到本地文件或SharedPreferences
。 - 提供了多种存储和解析方法(如单个对象、列表等)。
- 使用
- 工具类:封装了
GsonUtils
,方便复用。