如何获取GitHub用户所有仓库并使用Moshi解析无键JSON数组
用Moshi解析无键JSON数组到Kotlin数据类(GitHub仓库列表场景)
我明白你遇到的问题了——GitHub API返回的仓库列表是一个没有外层键的纯JSON数组,平时用Moshi大多处理带外层键的对象,这种数组确实需要稍微调整下解析逻辑,其实解决起来很简单,我给你一步步拆解代码示例:
第一步:定义GitHub仓库对应的数据类
先根据API返回的JSON结构,创建匹配的数据类,把你需要的字段都加上,字段名如果和JSON里的不一致,可以用@Json注解映射:
import com.squareup.moshi.Json import com.squareup.moshi.JsonClass @JsonClass(generateAdapter = true) data class GitHubRepo( val id: Long, val node_id: String, // 示例:映射JSON里的name字段到Kotlin的repoName属性 @Json(name = "name") val repoName: String, // 仓库描述可能为空,所以用可空类型 @Json(name = "description") val repoDescription: String?, // 可以继续添加你需要的其他字段,比如star数量、仓库地址等 val stargazers_count: Int, val html_url: String )
@JsonClass(generateAdapter = true)是让Moshi自动生成解析适配器,避免手动写适配器的麻烦。
第二步:核心解析逻辑(处理无键数组)
因为返回的是数组,我们需要明确告诉Moshi要解析成List<GitHubRepo>类型,这里有两种常用实现方式:
方式一:用Moshi的Types类创建类型令牌(兼容所有Kotlin版本)
由于泛型擦除的问题,Moshi需要明确的类型信息才能正确解析,我们可以用Types.newParameterizedType来创建列表的类型令牌:
import com.squareup.moshi.Moshi import com.squareup.moshi.Types fun parseGitHubRepos(jsonString: String): List<GitHubRepo> { // 初始化Moshi实例 val moshi = Moshi.Builder().build() // 创建List<GitHubRepo>的类型令牌 val repoListType = Types.newParameterizedType(List::class.java, GitHubRepo::class.java) // 获取对应的解析适配器 val adapter = moshi.adapter<List<GitHubRepo>>(repoListType) // 解析JSON字符串,为空的话返回空列表避免空指针 return adapter.fromJson(jsonString) ?: emptyList() }
方式二:用Kotlin的typeOf(Kotlin 1.9+版本可用,更简洁)
如果你用的是较新的Kotlin版本,可以用typeOf简化类型令牌的创建:
import com.squareup.moshi.Moshi import kotlin.reflect.typeOf fun parseGitHubRepos(jsonString: String): List<GitHubRepo> { val moshi = Moshi.Builder().build() val adapter = moshi.adapter<List<GitHubRepo>>(typeOf<List<GitHubRepo>>()) return adapter.fromJson(jsonString) ?: emptyList() }
额外优化:配合Retrofit请求API
如果你是用Retrofit来调用GitHub API,那更省心——直接在接口方法里返回List<GitHubRepo>即可,Retrofit会自动和Moshi协同处理数组解析,不需要手动处理类型令牌:
import retrofit2.http.GET import retrofit2.http.Path interface GitHubApiService { // 请求指定用户的仓库列表 @GET("users/{username}/repos") suspend fun getUserRepos(@Path("username") username: String): List<GitHubRepo> }
这样发起请求后,Retrofit会自动把API返回的无键JSON数组转换成List<GitHubRepo>对象列表,直接用就行。
内容的提问来源于stack exchange,提问作者foseja
相关产品推荐
相关产品推荐

