You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Android中使用Retrofit解析JSON数组

在Android中使用Retrofit解析嵌套JSON菜单数组的完整方案

Hey there! Let's walk through exactly how to parse this nested menu JSON structure using Retrofit in your Android project. I'll break it down step by step so you can follow along easily.

1. 先定义匹配JSON结构的数据模型

First things first: we need to create data classes (or POJOs for Java) that mirror the JSON structure. Notice the nested subMenus array—this means our model will reference itself recursively.

Kotlin 数据类

Kotlin's data classes make this super clean, and we'll use nullable types for fields that can be null (like icon and desc):

data class Menu(
    val name: String,
    val link: String,
    val menuId: String,
    val icon: String?,
    val desc: String?,
    val selected: Boolean,
    val subMenus: List<Menu> // 递归定义子菜单列表
)

Java POJO类

If you're using Java, you'll need a standard POJO with getters/setters (or use Lombok to auto-generate them). We'll use @SerializedName to explicitly map fields (this is optional if your field names match the JSON exactly, but it's safer for future changes):

import com.google.gson.annotations.SerializedName;
import java.util.List;

public class Menu {
    @SerializedName("name")
    private String name;
    @SerializedName("link")
    private String link;
    @SerializedName("menuId")
    private String menuId;
    @SerializedName("icon")
    private String icon;
    @SerializedName("desc")
    private String desc;
    @SerializedName("selected")
    private boolean selected;
    @SerializedName("subMenus")
    private List<Menu> subMenus;

    // Getters and Setters
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public String getLink() { return link; }
    public void setLink(String link) { this.link = link; }
    public String getMenuId() { return menuId; }
    public void setMenuId(String menuId) { this.menuId = menuId; }
    public String getIcon() { return icon; }
    public void setIcon(String icon) { this.icon = icon; }
    public String getDesc() { return desc; }
    public void setDesc(String desc) { this.desc = desc; }
    public boolean isSelected() { return selected; }
    public void setSelected(boolean selected) { this.selected = selected; }
    public List<Menu> getSubMenus() { return subMenus; }
    public void setSubMenus(List<Menu> subMenus) { this.subMenus = subMenus; }
}

2. 添加Retrofit和Gson依赖

Add these dependencies to your app-level build.gradle file (use the latest stable versions if available):

dependencies {
    // Retrofit核心库
    implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    // Gson转换器,用于将JSON解析为我们的数据模型
    implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
}

3. 创建Retrofit API接口

Define an interface to describe your API request. Based on the JSON you provided, the root object is a single Menu (not an array)—adjust this if your actual API returns a list of menus:

import retrofit2.Call
import retrofit2.http.GET

interface MenuApiService {
    // 将"menu-endpoint"替换为你的实际API端点路径
    @GET("menu-endpoint")
    fun fetchMenu(): Call<Menu>

    // 如果你的API返回菜单数组,改为下面这行:
    // fun fetchMenus(): Call<List<Menu>>
}

4. 初始化Retrofit实例

Set up Retrofit with your API base URL and the Gson converter:

val retrofit = Retrofit.Builder()
    .baseUrl("https://your-api-base-url.com/") // 替换为你的实际基础URL
    .addConverterFactory(GsonConverterFactory.create())
    .build()

val menuApi = retrofit.create(MenuApiService::class.java)

5. 发起请求并解析数据

Use Retrofit's asynchronous enqueue method to fetch and parse the data (this avoids blocking the main thread):

menuApi.fetchMenu().enqueue(object : retrofit2.Callback<Menu> {
    override fun onResponse(call: Call<Menu>, response: retrofit2.Response<Menu>) {
        if (response.isSuccessful) {
            val rootMenu = response.body()
            rootMenu?.let {
                // 成功解析菜单数据!现在可以开始处理它了
                // 示例:获取Dashboard子菜单
                val dashboardMenu = it.subMenus.firstOrNull { menu -> menu.menuId == "das" }
                dashboardMenu?.let {
                    Log.d("MenuParser", "Dashboard Link: ${it.link}")
                }
                // 递归遍历所有嵌套菜单
                traverseMenu(it)
            }
        } else {
            // 处理非2xx状态码的响应
            Log.e("MenuParser", "Request failed with code: ${response.code()}")
        }
    }

    override fun onFailure(call: Call<Menu>, t: Throwable) {
        // 处理网络错误或请求失败
        Log.e("MenuParser", "Request failed: ${t.message}")
    }
})

// 递归遍历所有菜单的辅助函数
private fun traverseMenu(menu: Menu) {
    Log.d("MenuParser", "Menu Name: ${menu.name}, ID: ${menu.menuId}")
    menu.subMenus.forEach { subMenu ->
        traverseMenu(subMenu)
    }
}

关键注意事项

  • 递归结构处理:subMenus字段定义为List<Menu>,Gson会自动递归解析嵌套的JSON数组,无需额外配置。
  • 可空字段处理:icon和desc可能为null,所以Kotlin中使用可空类型、Java中允许字段为null是避免解析错误的关键。
  • 根对象类型确认:务必确认你的API返回的是单个Menu对象还是Menu数组,对应调整API接口和回调的泛型类型。
  • 线程安全:Retrofit的enqueue方法在后台线程执行请求,回调结果在主线程返回,所以可以直接在回调中更新UI。

内容的提问来源于stack exchange,提问作者Deepak Rao

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 07:05:38